common/netlink.cpp (90 lines of code) (raw):

#include "common/logger.h" #include "common/netlink.h" #include "common/netdispatcher.h" #include <errno.h> #include <system_error> #include <cstring> using namespace swss; using namespace std; NetLink::NetLink(int pri) : Selectable(pri), m_socket(NULL) { m_socket = nl_socket_alloc(); if (!m_socket) { SWSS_LOG_ERROR("Unable to allocated netlink socket"); throw system_error(make_error_code(errc::address_not_available), "Unable to allocated netlink socket"); } nl_socket_disable_seq_check(m_socket); nl_socket_modify_cb(m_socket, NL_CB_VALID, NL_CB_CUSTOM, onNetlinkMsg, this); int err = nl_connect(m_socket, NETLINK_ROUTE); if (err < 0) { SWSS_LOG_ERROR("Unable to connect netlink socket: %s", nl_geterror(err)); nl_socket_free(m_socket); m_socket = NULL; throw system_error(make_error_code(errc::address_not_available), "Unable to connect netlink socket"); } nl_socket_set_nonblocking(m_socket); /* Set socket buffer size to 16MB */ nl_socket_set_buffer_size(m_socket, 16777216, 0); } NetLink::~NetLink() { if (m_socket != NULL) { nl_close(m_socket); nl_socket_free(m_socket); } } void NetLink::registerGroup(int rtnlGroup) { int err = nl_socket_add_membership(m_socket, rtnlGroup); if (err < 0) { SWSS_LOG_ERROR("Unable to register to group %d: %s", rtnlGroup, nl_geterror(err)); throw system_error(make_error_code(errc::address_not_available), "Unable to register group"); } } void NetLink::dumpRequest(int rtmGetCommand) { int err = nl_rtgen_request(m_socket, rtmGetCommand, AF_UNSPEC, NLM_F_DUMP); if (err < 0) { SWSS_LOG_ERROR("Unable to request dump on group %d: %s", rtmGetCommand, nl_geterror(err)); throw system_error(make_error_code(errc::address_not_available), "Unable to request dump"); } } int NetLink::getFd() { return nl_socket_get_fd(m_socket); } uint64_t NetLink::readData() { int err; do { err = nl_recvmsgs_default(m_socket); } while(err == -NLE_INTR); // Retry if the process was interrupted by a signal if (err < 0) { if (err == -NLE_NOMEM) SWSS_LOG_ERROR("netlink reports out of memory on reading a netlink socket. High possibility of a lost message"); else if (err == -NLE_AGAIN) SWSS_LOG_DEBUG("netlink reports NLE_AGAIN on reading a netlink socket"); else SWSS_LOG_ERROR("netlink reports an error=%d on reading a netlink socket", err); } return 0; } int NetLink::onNetlinkMsg(struct nl_msg *msg, void *arg) { NetDispatcher::getInstance().onNetlinkMessage(msg); return NL_OK; }