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 <adharkar@vmware.com>
This commit is contained in:
Ameya Dharkar 2019-05-16 17:29:08 -07:00
parent fbe748e59f
commit 9da60d0a19
3 changed files with 72 additions and 1 deletions

View File

@ -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);

View File

@ -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 */

View File

@ -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