Skip to content

Commit bb537bd

Browse files
committed
issue: 569177 use netlink to define alias interface base name
1 parent d0714a5 commit bb537bd

File tree

4 files changed

+159
-66
lines changed

4 files changed

+159
-66
lines changed

src/vma/dev/net_device_table_mgr.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,10 @@ int net_device_table_mgr::map_net_devices()
244244
}
245245

246246
bool valid = false;
247-
if (ifa->ifa_flags & IFF_MASTER) {
247+
248+
char base_ifname[IFNAMSIZ];
249+
get_base_interface_name((const char*)(ifa->ifa_name), base_ifname, sizeof(base_ifname));
250+
if (check_device_exist(base_ifname, BOND_DEVICE_FILE)) {
248251
// this is a bond interface (or a vlan/alias over bond), find the slaves
249252
valid = verify_bond_ipoib_or_eth_qp_creation(ifa);
250253
} else {

src/vma/dev/net_device_val.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -737,9 +737,7 @@ void net_device_val_eth::configure(struct ifaddrs* ifa, struct rdma_cm_id* cma_i
737737
nd_logpanic("m_p_L2_addr allocation error");
738738
}
739739
BULLSEYE_EXCLUDE_BLOCK_END
740-
741740
create_br_address(m_name.c_str());
742-
743741
m_vlan = get_vlan_id_from_ifname(m_name.c_str());
744742
if (m_vlan && m_bond != NO_BOND && m_bond_fail_over_mac == 1) {
745743
vlog_printf(VLOG_WARNING, " ******************************************************************\n");

src/vma/util/utils.cpp

Lines changed: 144 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,14 @@
3737
#include <sys/resource.h>
3838
#include <string.h>
3939
#include <iostream>
40+
#include <list>
4041
#include "vma/util/if.h"
4142
#include <sys/stat.h>
4243
#include <linux/if_ether.h>
4344
#include <linux/if_vlan.h>
4445
#include <linux/sockios.h>
46+
#include <linux/netlink.h>
47+
#include <linux/rtnetlink.h>
4548
#include <math.h>
4649
#include <linux/ip.h> //IP header (struct iphdr) definition
4750
#include <netinet/udp.h>
@@ -84,6 +87,7 @@ int get_sys_max_fd_num(int def_max_fd /*=1024*/)
8487
return def_max_fd;
8588
}
8689

90+
//keep order of checks
8791
int get_base_interface_name(const char *if_name, char *base_ifname, size_t sz_base_ifname)
8892
{
8993
BULLSEYE_EXCLUDE_BLOCK_START
@@ -93,70 +97,25 @@ int get_base_interface_name(const char *if_name, char *base_ifname, size_t sz_ba
9397
BULLSEYE_EXCLUDE_BLOCK_END
9498
memset(base_ifname, 0, sz_base_ifname);
9599

96-
if (get_vlan_base_name_from_ifname(if_name, base_ifname, sz_base_ifname)) {
100+
//bond
101+
if (check_device_exist(if_name, BOND_DEVICE_FILE)) {
102+
snprintf(base_ifname, sz_base_ifname, "%s" ,if_name);
97103
return 0;
98104
}
99-
100-
//Am I already the base (not virtual, not alias, can be bond)
101-
if ((!check_device_exist(if_name, VIRTUAL_DEVICE_FOLDER) ||
102-
check_device_exist(if_name, BOND_DEVICE_FILE)) && !strstr(if_name, ":")) {
105+
//vlan
106+
if (check_device_exist(if_name, VIRTUAL_DEVICE_FOLDER) && get_vlan_base_name_from_ifname(if_name, base_ifname, sizeof base_ifname)) {
107+
return 0;
108+
}
109+
//pysical interface or bond
110+
if (check_device_exist(if_name, FLAGS_PARAM_FILE)) {
103111
snprintf(base_ifname, sz_base_ifname, "%s" ,if_name);
104112
return 0;
105113
}
106-
107-
unsigned char vlan_if_address[MAX_L2_ADDR_LEN];
108-
const size_t ADDR_LEN = get_local_ll_addr(if_name, vlan_if_address, MAX_L2_ADDR_LEN, false);
109-
if (ADDR_LEN > 0) {
110-
struct ifaddrs *ifaddr, *ifa;
111-
int rc = getifaddrs(&ifaddr);
112-
BULLSEYE_EXCLUDE_BLOCK_START
113-
if (rc == -1) {
114-
__log_err("getifaddrs failed");
115-
return -1;
116-
}
117-
BULLSEYE_EXCLUDE_BLOCK_END
118-
119-
for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
120-
if (!strcmp(ifa->ifa_name, if_name)) {
121-
continue;
122-
}
123-
if (ifa->ifa_flags & IFF_SLAVE) {
124-
//bond slave
125-
continue;
126-
}
127-
128-
if (strstr(ifa->ifa_name, ":")) {
129-
//alias
130-
continue;
131-
}
132-
133-
if (check_device_exist(ifa->ifa_name, VIRTUAL_DEVICE_FOLDER)) {
134-
//virtual
135-
if (!check_device_exist(ifa->ifa_name, BOND_DEVICE_FILE)) {
136-
continue;
137-
}
138-
}
139-
140-
unsigned char tmp_mac[ADDR_LEN];
141-
if (ADDR_LEN == get_local_ll_addr(ifa->ifa_name, tmp_mac, ADDR_LEN, false)) {
142-
int size_to_compare;
143-
if (ADDR_LEN == ETH_ALEN) size_to_compare = ETH_ALEN;
144-
else size_to_compare = IPOIB_HW_ADDR_GID_LEN;
145-
int offset = ADDR_LEN - size_to_compare;
146-
if (0 == memcmp(vlan_if_address + offset, tmp_mac + offset, size_to_compare)) {
147-
snprintf(base_ifname, sz_base_ifname, "%s" ,ifa->ifa_name);
148-
freeifaddrs(ifaddr);
149-
__log_dbg("Found base_ifname %s for interface %s", base_ifname, if_name);
150-
return 0;
151-
}
152-
}
153-
}
154-
155-
freeifaddrs(ifaddr);
114+
//alias
115+
if(get_alias_base_name_from_ifname(if_name, base_ifname, sz_base_ifname)) {
116+
return 0;
156117
}
157-
snprintf(base_ifname, sz_base_ifname, "%s" ,if_name);
158-
__log_dbg("no base for %s", base_ifname, if_name);
159-
return 0;
118+
return -1;
160119
}
161120

162121
unsigned short compute_ip_checksum(const unsigned short *buf, unsigned int nshort_words)
@@ -749,6 +708,126 @@ size_t get_vlan_base_name_from_ifname(const char* ifname, char* base_ifname, siz
749708
return 0;
750709
}
751710

711+
size_t get_alias_base_name_from_ifname(const char* ifname, char* base_ifname, size_t sz_base_ifname)
712+
{
713+
int ret;
714+
//create netlink socket
715+
int sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
716+
if (sock < 0) {
717+
__log_dbg("could not open netlink socket (%d %m)", errno);
718+
return 0;
719+
}
720+
struct sockaddr_nl snl;
721+
memset(&snl, 0, sizeof(snl));
722+
snl.nl_family = AF_NETLINK;
723+
snl.nl_pid = getpid();
724+
if (bind(sock, (struct sockaddr *)&snl, sizeof(snl)) < 0) {
725+
__log_dbg("could not bind netlink socket (%d %m)", errno);
726+
close(sock);
727+
return 0;
728+
}
729+
730+
struct
731+
{
732+
struct nlmsghdr nlh;
733+
struct rtgenmsg g;
734+
} req;
735+
736+
//prepare request header
737+
memset(&req, 0, sizeof(req));
738+
req.nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg));
739+
req.nlh.nlmsg_type = RTM_GETADDR;//RTM_GETLINK;
740+
req.nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
741+
req.nlh.nlmsg_seq = 1;
742+
req.nlh.nlmsg_pid = getpid();
743+
req.g.rtgen_family = AF_PACKET;
744+
745+
struct sockaddr_nl kernel;
746+
struct msghdr rtnl_msg;
747+
struct iovec io;
748+
memset(&rtnl_msg, 0, sizeof(rtnl_msg));
749+
memset(&kernel, 0, sizeof(kernel));
750+
751+
kernel.nl_family = AF_NETLINK;
752+
io.iov_base = &req;
753+
io.iov_len = req.nlh.nlmsg_len;
754+
rtnl_msg.msg_iov = &io;
755+
rtnl_msg.msg_iovlen = 1;
756+
rtnl_msg.msg_name = &kernel;
757+
rtnl_msg.msg_namelen = sizeof(kernel);
758+
759+
ret = sendmsg(sock, (struct msghdr *) &rtnl_msg, 0);
760+
if (ret < 0) {
761+
__log_dbg("error sending netlink request (%d %m)", errno);
762+
close(sock);
763+
return 0;
764+
}
765+
766+
unsigned char buffer[10*1024];
767+
struct nlmsghdr *msg_ptr;
768+
struct msghdr rtnl_reply;
769+
struct iovec io_reply;
770+
771+
memset(&io_reply, 0, sizeof(io_reply));
772+
memset(&rtnl_reply, 0, sizeof(rtnl_reply));
773+
774+
io.iov_base = buffer;
775+
io.iov_len = 10*1024;
776+
rtnl_reply.msg_iov = &io;
777+
rtnl_reply.msg_iovlen = 1;
778+
rtnl_reply.msg_name = &kernel;
779+
rtnl_reply.msg_namelen = sizeof(kernel);
780+
ret = recvmsg(sock, &rtnl_reply, 0); /* read lots of data */
781+
if (ret < 0) {
782+
__log_dbg("error receiving netlink data (%d %m)", errno);
783+
close(sock);
784+
return 0;
785+
}
786+
787+
typedef std::pair<char*, int> int_index;
788+
list<int_index> interface_index_list;
789+
int my_index = -1;
790+
for (msg_ptr = (struct nlmsghdr *) buffer; NLMSG_OK(msg_ptr, (unsigned short)ret) && msg_ptr->nlmsg_type!= NLMSG_DONE; msg_ptr = NLMSG_NEXT(msg_ptr, ret)) {
791+
if (msg_ptr->nlmsg_type == RTM_NEWADDR) {
792+
struct ifaddrmsg *iface;
793+
struct rtattr *attribute;
794+
int len;
795+
796+
iface = (struct ifaddrmsg *)NLMSG_DATA(msg_ptr);
797+
len = msg_ptr->nlmsg_len - NLMSG_LENGTH(sizeof(*iface));
798+
//save interface and it's index in map
799+
for (attribute = IFLA_RTA(iface); RTA_OK(attribute, len); attribute = RTA_NEXT(attribute, len)) {
800+
if(attribute->rta_type == IFA_LABEL) {
801+
char* attr_name = (char*)RTA_DATA(attribute);
802+
int_index elem;
803+
elem.first = attr_name;
804+
elem.second = iface->ifa_index;
805+
interface_index_list.push_back(elem);
806+
//interface_index_list.add()[if_name] = iface->ifa_index;
807+
if (strcmp(attr_name, ifname) == 0) {
808+
my_index = iface->ifa_index;
809+
}
810+
}
811+
}
812+
}
813+
}
814+
815+
//find a physical or bond interface that has the same index as me
816+
size_t name_size = 0;
817+
list<int_index>::iterator interface_index_iter;
818+
for (interface_index_iter=interface_index_list.begin(); interface_index_iter!=interface_index_list.end(); interface_index_iter++) {
819+
if ((interface_index_iter->second == my_index) && strcmp(interface_index_iter->first, ifname) != 0) {
820+
//check that this isn't another alias
821+
if (check_device_exist(interface_index_iter->first, FLAGS_PARAM_FILE)) {
822+
snprintf(base_ifname, sz_base_ifname, "%s" ,interface_index_iter->first);
823+
name_size = strlen(interface_index_iter->first);
824+
}
825+
}
826+
}
827+
close(sock);
828+
return name_size;
829+
}
830+
752831
#if _BullseyeCoverage
753832
#pragma BullseyeCoverage off
754833
#endif
@@ -946,12 +1025,14 @@ size_t get_local_ll_addr(IN const char * ifname, OUT unsigned char* addr, IN int
9461025
{
9471026
char l2_addr_path[256] = {0};
9481027
char buf[256] = {0};
949-
950-
// In case of alias (ib0/eth0:xx) take only the device name for that interface (ib0/eth0)
951-
size_t ifname_len = strcspn(ifname, ":"); // TODO: this is temp code till we get base interface for any alias format of an interface
9521028
const char * l2_addr_path_fmt = is_broadcast ? L2_BR_ADDR_FILE_FMT : L2_ADDR_FILE_FMT;
953-
snprintf(l2_addr_path, sizeof(l2_addr_path)-1, l2_addr_path_fmt, ifname_len, ifname);
954-
1029+
char base_ifname[32];
1030+
size_t ifname_len = get_alias_base_name_from_ifname(ifname, base_ifname, sizeof base_ifname);
1031+
if (ifname_len > 0) {
1032+
snprintf(l2_addr_path, sizeof(l2_addr_path)-1, l2_addr_path_fmt, ifname_len, base_ifname);
1033+
} else {
1034+
snprintf(l2_addr_path, sizeof(l2_addr_path)-1, l2_addr_path_fmt, strlen(ifname), ifname);
1035+
}
9551036
int len = priv_read_file(l2_addr_path, buf, sizeof(buf));
9561037
int bytes_len = (len + 1) / 3; // convert len from semantic of hex format L2 address with ':' delimiter (and optional newline character) into semantic of byte array
9571038
__log_dbg("ifname=%s un-aliased-ifname=%.*s l2_addr_path=%s l2-addr=%s (addr-bytes_len=%d)", ifname, ifname_len, ifname, l2_addr_path, buf, bytes_len);

src/vma/util/utils.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,17 @@ uint16_t get_vlan_id_from_ifname(const char* ifname);
325325
*/
326326
size_t get_vlan_base_name_from_ifname(const char* ifname, char* base_ifname, size_t sz_base_ifname);
327327

328+
/**
329+
* Get alias base name from interface name
330+
*
331+
* @param ifname input interface name of device (e.g. eth2, eth2.5)
332+
* @param base_ifname output base interface name of device (e.g. eth2)
333+
* @param sz_base_ifname input the size of base_ifname param
334+
* @return the alias base name length or 0 if not found
335+
*/
336+
337+
size_t get_alias_base_name_from_ifname(const char* ifname, char* base_ifname, size_t sz_base_ifname);
338+
328339
/**
329340
* Get peer node IPoIB QP number (remote_qpn) from the peer's IP
330341
* address

0 commit comments

Comments
 (0)