diff options
author | Ameya Dharkar <adharkar@vmware.com> | 2019-05-17 03:38:03 +0200 |
---|---|---|
committer | Ameya Dharkar <adharkar@vmware.com> | 2019-05-17 19:50:21 +0200 |
commit | 9d21b7c6f04146b518d0275d1c7f4388d9b33444 (patch) | |
tree | 33cad7f29db19cc034d5a1a9a2cae80ea8ce4c6d /zebra/zebra_fpm_netlink.c | |
parent | Merge pull request #4354 from donaldsharp/more_gcc_9_1_werror (diff) | |
download | frr-9d21b7c6f04146b518d0275d1c7f4388d9b33444.tar.xz frr-9d21b7c6f04146b518d0275d1c7f4388d9b33444.zip |
Zebra: Handle VxLAN encap in netlink rtmsg for FPM
- For data plane processing of VxLAN routes, add encap type and L3VNI info to
rtmsg message for FPM.
- Add "RTA_ENCAP_TYPE" attribute for VxLAN encap with value 100.
This value is not currently used for RTA_ENCAP_TYPE for any encap.
- If "RTA_ENCAP_TYPE" is 100, add "RTA_ENCAP" attribute with "RTA_VNI" as a
nested attribute of RTA_ENCAP
Format of RTA_VNI attribute:
Len(2 bytes) type (2 bytes) Value(4 bytes)(VNI)
00 08 : 00 00 : 1000
RTA_VNI attribute is a custom attribute.
Signed-off-by: Ameya Dharkar <adharkar@vmware.com>
Diffstat (limited to 'zebra/zebra_fpm_netlink.c')
-rw-r--r-- | zebra/zebra_fpm_netlink.c | 116 |
1 files changed, 112 insertions, 4 deletions
diff --git a/zebra/zebra_fpm_netlink.c b/zebra/zebra_fpm_netlink.c index 065bdee20..651df5e6f 100644 --- a/zebra/zebra_fpm_netlink.c +++ b/zebra/zebra_fpm_netlink.c @@ -41,6 +41,7 @@ #include "nexthop.h" #include "zebra/zebra_fpm_private.h" +#include "zebra/zebra_vxlan_private.h" /* * addr_to_a @@ -102,6 +103,51 @@ static size_t af_addr_size(uint8_t af) } /* + * We plan to use RTA_ENCAP_TYPE attribute for VxLAN encap as well. + * Currently, values 0 to 8 for this attribute are used by lwtunnel_encap_types + * So, we cannot use these values for VxLAN encap. + */ +enum fpm_nh_encap_type_t { + FPM_NH_ENCAP_NONE = 0, + FPM_NH_ENCAP_VXLAN = 100, + FPM_NH_ENCAP_MAX, +}; + +/* + * fpm_nh_encap_type_to_str + */ +static const char *fpm_nh_encap_type_to_str(enum fpm_nh_encap_type_t encap_type) +{ + switch (encap_type) { + case FPM_NH_ENCAP_NONE: + return "none"; + + case FPM_NH_ENCAP_VXLAN: + return "VxLAN"; + + case FPM_NH_ENCAP_MAX: + return "invalid"; + } + + return "invalid"; +} + +struct vxlan_encap_info_t { + vni_t vni; +}; + +enum vxlan_encap_info_type_t { + VXLAN_VNI = 0, +}; + +struct fpm_nh_encap_info_t { + enum fpm_nh_encap_type_t encap_type; + union { + struct vxlan_encap_info_t vxlan_encap; + }; +}; + +/* * netlink_nh_info_t * * Holds information about a single nexthop for netlink. These info @@ -118,6 +164,7 @@ typedef struct netlink_nh_info_t_ { */ int recursive; enum nexthop_types_t type; + struct fpm_nh_encap_info_t encap_info; } netlink_nh_info_t; /* @@ -151,10 +198,12 @@ typedef struct netlink_route_info_t_ { * Returns TRUE if a nexthop was added, FALSE otherwise. */ static int netlink_route_info_add_nh(netlink_route_info_t *ri, - struct nexthop *nexthop) + struct nexthop *nexthop, + struct route_entry *re) { netlink_nh_info_t nhi; union g_addr *src; + zebra_l3vni_t *zl3vni = NULL; memset(&nhi, 0, sizeof(nhi)); src = NULL; @@ -186,6 +235,17 @@ static int netlink_route_info_add_nh(netlink_route_info_t *ri, if (!nhi.gateway && nhi.if_index == 0) return 0; + if (re && CHECK_FLAG(re->flags, ZEBRA_FLAG_EVPN_ROUTE)) { + nhi.encap_info.encap_type = FPM_NH_ENCAP_VXLAN; + + zl3vni = zl3vni_from_vrf(ri->rtm_table); + if (zl3vni && is_l3vni_oper_up(zl3vni)) { + + /* Add VNI to VxLAN encap info */ + nhi.encap_info.vxlan_encap.vni = zl3vni->vni; + } + } + /* * We have a valid nhi. Copy the structure over to the route_info. */ @@ -277,7 +337,7 @@ static int netlink_route_info_fill(netlink_route_info_t *ri, int cmd, && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) || (cmd == RTM_DELROUTE && CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED))) { - netlink_route_info_add_nh(ri, nexthop); + netlink_route_info_add_nh(ri, nexthop, re); } } @@ -303,6 +363,10 @@ static int netlink_route_info_encode(netlink_route_info_t *ri, char *in_buf, unsigned int nexthop_num = 0; size_t buf_offset; netlink_nh_info_t *nhi; + enum fpm_nh_encap_type_t encap; + struct rtattr *nest; + struct vxlan_encap_info_t *vxlan; + int nest_len; struct { struct nlmsghdr n; @@ -355,6 +419,26 @@ static int netlink_route_info_encode(netlink_route_info_t *ri, char *in_buf, addattr32(&req->n, in_buf_len, RTA_OIF, nhi->if_index); } + encap = nhi->encap_info.encap_type; + if (encap > FPM_NH_ENCAP_NONE) { + addattr_l(&req->n, in_buf_len, RTA_ENCAP_TYPE, &encap, + sizeof(uint16_t)); + switch (encap) { + case FPM_NH_ENCAP_NONE: + break; + case FPM_NH_ENCAP_VXLAN: + vxlan = &nhi->encap_info.vxlan_encap; + nest = addattr_nest(&req->n, in_buf_len, + RTA_ENCAP); + addattr32(&req->n, in_buf_len, VXLAN_VNI, + vxlan->vni); + addattr_nest_end(&req->n, nest); + break; + case FPM_NH_ENCAP_MAX: + break; + } + } + goto done; } @@ -388,6 +472,28 @@ static int netlink_route_info_encode(netlink_route_info_t *ri, char *in_buf, rtnh->rtnh_ifindex = nhi->if_index; } + encap = nhi->encap_info.encap_type; + if (encap > FPM_NH_ENCAP_NONE) { + rta_addattr_l(rta, sizeof(buf), RTA_ENCAP_TYPE, + &encap, sizeof(uint16_t)); + rtnh->rtnh_len += sizeof(struct rtattr) + + sizeof(uint16_t); + switch (encap) { + case FPM_NH_ENCAP_NONE: + break; + case FPM_NH_ENCAP_VXLAN: + vxlan = &nhi->encap_info.vxlan_encap; + nest = rta_nest(rta, sizeof(buf), RTA_ENCAP); + rta_addattr_l(rta, sizeof(buf), VXLAN_VNI, + &vxlan->vni, sizeof(uint32_t)); + nest_len = rta_nest_end(rta, nest); + rtnh->rtnh_len += nest_len; + break; + case FPM_NH_ENCAP_MAX: + break; + } + } + rtnh = RTNH_NEXT(rtnh); } @@ -424,10 +530,12 @@ static void zfpm_log_route_info(netlink_route_info_t *ri, const char *label) for (i = 0; i < ri->num_nhs; i++) { nhi = &ri->nhs[i]; - zfpm_debug(" Intf: %u, Gateway: %s, Recursive: %s, Type: %s", + zfpm_debug(" Intf: %u, Gateway: %s, Recursive: %s, Type: %s, Encap type: %s", nhi->if_index, addr_to_a(ri->af, nhi->gateway), nhi->recursive ? "yes" : "no", - nexthop_type_to_str(nhi->type)); + nexthop_type_to_str(nhi->type), + fpm_nh_encap_type_to_str(nhi->encap_info.encap_type) + ); } } |