From 9da60d0a19b1a838865e37e6554481dc851c1bcb Mon Sep 17 00:00:00 2001 From: Ameya Dharkar Date: Thu, 16 May 2019 17:29:08 -0700 Subject: [PATCH] Zebra: Build nelink message for RMAC updates - Function "zfpm_netlink_encode_mac()" builds a netlink message for RMAC updates. - To build a netlink message for RMAC updates, we use "ndmsg" in rtlink. - FPM Message structure is: FPM header -> nlmsg header -> ndmsg fields -> ndmsg attributes - Netlink message will look like: {'ndm_type': 0, 'family': 7, '__pad': (), 'header': {'flags': 1281, 'length':64, 'type': 28, 'pid': 0, 'sequence_number': 0}, 'state': 2, 'flags': 22, 'attrs': [('NDA_LLADDR', 'b2:66:eb:b9:5b:d3'), ('NDA_DST', '10.100.0.2'), ('NDA_MASTER', 11), ('NDA_VNI', 1000)], 'ifindex': 18} - Message details: nlmsghdr.nlmsg_type = RTM_NEWNEIGH(28) or RTM_DELNEIGH(29) nlmsghdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_REPLACE for "add" , "NLM_F_REQUEST" for delete. ndmsg.ndm_family = AF_BRIDGE ndmsg.ndm_ifindex = vxlan_if (ifindex) ndmsg.ndm_state = NUD_REACHABLE ndmsg.ndm_flags |= NTF_SELF | NTF_MASTER | NTF_EXT_LEARNED Attribute "NDA_LLADDR" for MAC address Attribute "NDA_DST" for remote vtep ip Attribute "NDA_MASTER" for bridge interface ifindex. Attribute "NDA_VNI" for VNI id. Signed-off-by: Ameya Dharkar --- zebra/zebra_fpm.c | 7 ++++- zebra/zebra_fpm_netlink.c | 63 +++++++++++++++++++++++++++++++++++++++ zebra/zebra_fpm_private.h | 3 ++ 3 files changed, 72 insertions(+), 1 deletion(-) diff --git a/zebra/zebra_fpm.c b/zebra/zebra_fpm.c index 83d0dba61f..3e74db8111 100644 --- a/zebra/zebra_fpm.c +++ b/zebra/zebra_fpm.c @@ -1052,6 +1052,11 @@ static inline int zfpm_encode_mac(struct fpm_mac_info_t *mac, char *in_buf, case ZFPM_MSG_FORMAT_NONE: break; case ZFPM_MSG_FORMAT_NETLINK: +#ifdef HAVE_NETLINK + len = zfpm_netlink_encode_mac(mac, in_buf, in_buf_len); + assert(fpm_msg_align(len) == len); + *msg_type = FPM_MSG_TYPE_NETLINK; +#endif /* HAVE_NETLINK */ break; case ZFPM_MSG_FORMAT_PROTOBUF: break; @@ -1100,7 +1105,7 @@ static int zfpm_build_mac_updates(void) data = fpm_msg_data(hdr); data_len = zfpm_encode_mac(mac, (char *)data, buf_end - data, &msg_type); - /* assert(data_len); */ + assert(data_len); hdr->msg_type = msg_type; msg_len = fpm_data_len_to_msg_len(data_len); diff --git a/zebra/zebra_fpm_netlink.c b/zebra/zebra_fpm_netlink.c index 2ac79b100c..4f2013585d 100644 --- a/zebra/zebra_fpm_netlink.c +++ b/zebra/zebra_fpm_netlink.c @@ -580,4 +580,67 @@ int zfpm_netlink_encode_route(int cmd, rib_dest_t *dest, struct route_entry *re, return netlink_route_info_encode(ri, in_buf, in_buf_len); } +/* + * zfpm_netlink_encode_mac + * + * Create a netlink message corresponding to the given MAC. + * + * Returns the number of bytes written to the buffer. 0 or a negative + * value indicates an error. + */ +int zfpm_netlink_encode_mac(struct fpm_mac_info_t *mac, char *in_buf, + size_t in_buf_len) +{ + char buf1[ETHER_ADDR_STRLEN]; + size_t buf_offset; + + struct { + struct nlmsghdr hdr; + struct ndmsg ndm; + char buf[0]; + } *req; + req = (void *)in_buf; + + buf_offset = ((char *)req->buf) - ((char *)req); + if (in_buf_len < buf_offset) + return 0; + memset(req, 0, buf_offset); + + /* Construct nlmsg header */ + req->hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg)); + req->hdr.nlmsg_type = CHECK_FLAG(mac->fpm_flags, ZEBRA_MAC_DELETE_FPM) ? + RTM_DELNEIGH : RTM_NEWNEIGH; + req->hdr.nlmsg_flags = NLM_F_REQUEST; + if (req->hdr.nlmsg_type == RTM_NEWNEIGH) + req->hdr.nlmsg_flags |= (NLM_F_CREATE | NLM_F_REPLACE); + + /* Construct ndmsg */ + req->ndm.ndm_family = AF_BRIDGE; + req->ndm.ndm_ifindex = mac->vxlan_if; + + req->ndm.ndm_state = NUD_REACHABLE; + req->ndm.ndm_flags |= NTF_SELF | NTF_MASTER; + if (CHECK_FLAG(mac->zebra_flags, + (ZEBRA_MAC_STICKY | ZEBRA_MAC_REMOTE_DEF_GW))) + req->ndm.ndm_state |= NUD_NOARP; + else + req->ndm.ndm_flags |= NTF_EXT_LEARNED; + + /* Add attributes */ + addattr_l(&req->hdr, in_buf_len, NDA_LLADDR, &mac->macaddr, 6); + addattr_l(&req->hdr, in_buf_len, NDA_DST, &mac->r_vtep_ip, 4); + addattr32(&req->hdr, in_buf_len, NDA_MASTER, mac->svi_if); + addattr32(&req->hdr, in_buf_len, NDA_VNI, mac->vni); + + assert(req->hdr.nlmsg_len < in_buf_len); + + zfpm_debug("Tx %s family %s ifindex %u MAC %s DEST %s", + nl_msg_type_to_str(req->hdr.nlmsg_type), + nl_family_to_str(req->ndm.ndm_family), req->ndm.ndm_ifindex, + prefix_mac2str(&mac->macaddr, buf1, sizeof(buf1)), + inet_ntoa(mac->r_vtep_ip)); + + return req->hdr.nlmsg_len; +} + #endif /* HAVE_NETLINK */ diff --git a/zebra/zebra_fpm_private.h b/zebra/zebra_fpm_private.h index 3ca39c45a9..c169ee8c22 100644 --- a/zebra/zebra_fpm_private.h +++ b/zebra/zebra_fpm_private.h @@ -92,6 +92,9 @@ extern int zfpm_netlink_encode_route(int cmd, rib_dest_t *dest, extern int zfpm_protobuf_encode_route(rib_dest_t *dest, struct route_entry *re, uint8_t *in_buf, size_t in_buf_len); +extern int zfpm_netlink_encode_mac(struct fpm_mac_info_t *mac, char *in_buf, + size_t in_buf_len); + extern struct route_entry *zfpm_route_for_update(rib_dest_t *dest); #ifdef __cplusplus -- 2.39.5