From: vivek Date: Fri, 25 Mar 2016 05:01:11 +0000 (-0700) Subject: Zebra: Fix handling of larger table-ids X-Git-Tag: frr-2.0-rc1~1038^2~2 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=ca46a78e872a8a991e7dc262d44c6e68860cf127;p=mirror%2Ffrr.git Zebra: Fix handling of larger table-ids Zebra code was not handling larger table-ids correctly. There were 2 issues: a) In the netlink interface, RTA_TABLE was never sent or processed. This pretty much limited the table-ids that zebra could understand to < 255. b) In the interface into the zebra RIB (in particular for protocols), there were some incorrect checks that again assumed the table id should be < 252 or be "main". This is valid only for the Default VRF (for now), for other VRFs, the table-id should be the value learnt from the kernel. These two issues are addressed with this change. Signed-off-by: Vivek Venkatraman Ticket: CM-10087, CM-10091 Reviewed By: CCR-4359 Testing Done: Manual --- diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index ffab76bbe6..b95ef8462b 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -850,12 +850,6 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h, if (rtm->rtm_type != RTN_UNICAST) return 0; - table = rtm->rtm_table; - if (!is_zebra_valid_kernel_table(table) && !is_zebra_main_routing_table(table)) - return 0; - - vrf_id = vrf_lookup_by_table(table); - len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg)); if (len < 0) return -1; @@ -873,6 +867,21 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h, if (rtm->rtm_src_len != 0) return 0; + /* Table corresponding to route. */ + if (tb[RTA_TABLE]) + table = *(int *) RTA_DATA (tb[RTA_TABLE]); + else + table = rtm->rtm_table; + + /* Map to VRF */ + vrf_id = vrf_lookup_by_table(table); + if (vrf_id == VRF_DEFAULT) + { + if (!is_zebra_valid_kernel_table(table) && + !is_zebra_main_routing_table(table)) + return 0; + } + /* Route which inserted by Zebra. */ if (rtm->rtm_protocol == RTPROT_ZEBRA) flags |= ZEBRA_FLAG_SELFROUTE; @@ -1045,12 +1054,6 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h, return 0; } - table = rtm->rtm_table; - if (!is_zebra_valid_kernel_table(table) && !is_zebra_main_routing_table(table)) - return 0; - - vrf_id = vrf_lookup_by_table(table); - len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg)); if (len < 0) return -1; @@ -1076,6 +1079,21 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h, return 0; } + /* Table corresponding to route. */ + if (tb[RTA_TABLE]) + table = *(int *) RTA_DATA (tb[RTA_TABLE]); + else + table = rtm->rtm_table; + + /* Map to VRF */ + vrf_id = vrf_lookup_by_table(table); + if (vrf_id == VRF_DEFAULT) + { + if (!is_zebra_valid_kernel_table(table) && + !is_zebra_main_routing_table(table)) + return 0; + } + index = 0; metric = 0; dest = NULL; @@ -1654,7 +1672,6 @@ netlink_route (int cmd, int family, void *dest, int length, void *gate, req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST; req.n.nlmsg_type = cmd; req.r.rtm_family = family; - req.r.rtm_table = table; req.r.rtm_dst_len = length; req.r.rtm_protocol = RTPROT_ZEBRA; req.r.rtm_scope = RT_SCOPE_UNIVERSE; @@ -1687,6 +1704,15 @@ netlink_route (int cmd, int family, void *dest, int length, void *gate, if (dest) addattr_l (&req.n, sizeof req, RTA_DST, dest, bytelen); + /* Table corresponding to this route. */ + if (table < 256) + req.r.rtm_table = table; + else + { + req.r.rtm_table = RT_TABLE_UNSPEC; + addattr32(&req.n, sizeof req, RTA_TABLE, table); + } + if (!discard) { if (gate) @@ -2071,7 +2097,6 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib, req.n.nlmsg_flags |= NLM_F_REPLACE; req.n.nlmsg_type = cmd; req.r.rtm_family = family; - req.r.rtm_table = rib->table; req.r.rtm_dst_len = p->prefixlen; req.r.rtm_protocol = RTPROT_ZEBRA; req.r.rtm_scope = RT_SCOPE_UNIVERSE; @@ -2105,6 +2130,15 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib, */ addattr32 (&req.n, sizeof req, RTA_PRIORITY, NL_DEFAULT_ROUTE_METRIC); + /* Table corresponding to this route. */ + if (rib->table < 256) + req.r.rtm_table = rib->table; + else + { + req.r.rtm_table = RT_TABLE_UNSPEC; + addattr32(&req.n, sizeof req, RTA_TABLE, rib->table); + } + if (discard) { if (cmd == RTM_NEWROUTE) diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 9679afe068..8a57473e63 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -2002,6 +2002,32 @@ rib_delnode (struct route_node *rn, struct rib *rib) } } +/* Lookup the routing table in a VRF based on both VRF-Id and table-id. + * NOTE: Table-id is relevant only in the Default VRF. + */ +static struct route_table * +zebra_vrf_table_with_table_id (afi_t afi, safi_t safi, + vrf_id_t vrf_id, u_int32_t table_id) +{ + struct route_table *table = NULL; + + if (afi >= AFI_MAX || safi >= SAFI_MAX) + return NULL; + + if (vrf_id == VRF_DEFAULT) + { + if (table_id == RT_TABLE_MAIN || + table_id == zebrad.rtm_table_default) + table = zebra_vrf_table (afi, safi, vrf_id); + else + table = zebra_vrf_other_route_table (afi, table_id, vrf_id); + } + else + table = zebra_vrf_table (afi, safi, vrf_id); + + return table; +} + int rib_add_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p, struct in_addr *gate, struct in_addr *src, @@ -2015,14 +2041,7 @@ rib_add_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p, struct nexthop *nexthop; /* Lookup table. */ - if ((table_id == RT_TABLE_MAIN) || (table_id == zebrad.rtm_table_default)) - { - table = zebra_vrf_table (AFI_IP, safi, vrf_id); - } - else - { - table = zebra_vrf_other_route_table (AFI_IP, table_id, vrf_id); - } + table = zebra_vrf_table_with_table_id (AFI_IP, safi, vrf_id, table_id); if (! table) return 0; @@ -2298,14 +2317,7 @@ rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib, safi_t safi) int ret = 0; /* Lookup table. */ - if ((rib->table == zebrad.rtm_table_default) || (rib->table == RT_TABLE_MAIN)) - { - table = zebra_vrf_table (AFI_IP, safi, rib->vrf_id); - } - else - { - table = zebra_vrf_other_route_table (AFI_IP, rib->table, rib->vrf_id); - } + table = zebra_vrf_table_with_table_id (AFI_IP, safi, rib->vrf_id, rib->table); if (! table) return 0; @@ -2390,14 +2402,7 @@ rib_delete_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p, char buf2[INET6_ADDRSTRLEN]; /* Lookup table. */ - if ((table_id == RT_TABLE_MAIN) || (table_id == zebrad.rtm_table_default)) - { - table = zebra_vrf_table (AFI_IP, safi, vrf_id); - } - else - { - table = zebra_vrf_other_route_table(AFI_IP, table_id, vrf_id); - } + table = zebra_vrf_table_with_table_id (AFI_IP, safi, vrf_id, table_id); if (! table) return 0; @@ -2966,14 +2971,7 @@ rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, struct nexthop *nexthop; /* Lookup table. */ - if ((table_id == RT_TABLE_MAIN) || (table_id == zebrad.rtm_table_default)) - { - table = zebra_vrf_table (AFI_IP6, safi, vrf_id); - } - else - { - table = zebra_vrf_other_route_table(AFI_IP6, table_id, vrf_id); - } + table = zebra_vrf_table_with_table_id (AFI_IP6, safi, vrf_id, table_id); if (! table) return 0; @@ -3078,7 +3076,6 @@ rib_add_ipv6_multipath (struct prefix *p, struct rib *rib, safi_t safi, struct rib *same = NULL; struct nexthop *nexthop; int ret = 0; - unsigned int table_id = 0; if (p->family == AF_INET) { @@ -3093,21 +3090,11 @@ rib_add_ipv6_multipath (struct prefix *p, struct rib *rib, safi_t safi, } else { - if (rib) - table_id = rib->table; - else + if (!rib) return 0; /* why are we getting called with NULL rib */ /* Lookup table. */ - if ((table_id == RT_TABLE_MAIN) || (table_id == zebrad.rtm_table_default)) - { - table = zebra_vrf_table (AFI_IP6, safi, rib->vrf_id); - } - else - { - table = zebra_vrf_other_route_table(AFI_IP6, table_id, rib->vrf_id); - } - + table = zebra_vrf_table_with_table_id (AFI_IP6, safi, rib->vrf_id, rib->table); if (! table) return 0; @@ -3215,14 +3202,7 @@ rib_delete_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, apply_mask_ipv6 (p); /* Lookup table. */ - if ((table_id == RT_TABLE_MAIN) || (table_id == zebrad.rtm_table_default)) - { - table = zebra_vrf_table (AFI_IP6, safi, vrf_id); - } - else - { - table = zebra_vrf_other_route_table(AFI_IP6, table_id, vrf_id); - } + table = zebra_vrf_table_with_table_id (AFI_IP6, safi, vrf_id, table_id); if (! table) return 0;