diff options
Diffstat (limited to 'zebra/rt_netlink.c')
| -rw-r--r-- | zebra/rt_netlink.c | 152 |
1 files changed, 82 insertions, 70 deletions
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index a80ab9d834..2b758c58d8 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -160,8 +160,8 @@ static inline int proto2zebra(int proto, int family) proto = ZEBRA_ROUTE_BGP; break; case RTPROT_OSPF: - proto = (family == AFI_IP) ? - ZEBRA_ROUTE_OSPF : ZEBRA_ROUTE_OSPF6; + proto = (family == AFI_IP) ? ZEBRA_ROUTE_OSPF + : ZEBRA_ROUTE_OSPF6; break; case RTPROT_ISIS: proto = ZEBRA_ROUTE_ISIS; @@ -194,16 +194,25 @@ static inline int proto2zebra(int proto, int family) /* Pending: create an efficient table_id (in a tree/hash) based lookup) */ -static vrf_id_t vrf_lookup_by_table(u_int32_t table_id) +static vrf_id_t vrf_lookup_by_table(u_int32_t table_id, ns_id_t ns_id) { struct vrf *vrf; struct zebra_vrf *zvrf; RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) { - if ((zvrf = vrf->info) == NULL || (zvrf->table_id != table_id)) + zvrf = vrf->info; + if (zvrf == NULL) continue; - - return zvrf_id(zvrf); + /* case vrf with netns : match the netnsid */ + if (vrf_is_backend_netns()) { + if (ns_id == zvrf_id(zvrf)) + return zvrf_id(zvrf); + } else { + /* VRF is VRF_BACKEND_VRF_LITE */ + if (zvrf->table_id != table_id) + continue; + return zvrf_id(zvrf); + } } return VRF_DEFAULT; @@ -220,7 +229,7 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl, u_char flags = 0; struct prefix p; struct prefix_ipv6 src_p = {}; - vrf_id_t vrf_id = VRF_DEFAULT; + vrf_id_t vrf_id; char anyaddr[16] = {0}; @@ -288,7 +297,7 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl, table = rtm->rtm_table; /* Map to VRF */ - vrf_id = vrf_lookup_by_table(table); + vrf_id = vrf_lookup_by_table(table, ns_id); if (vrf_id == VRF_DEFAULT) { if (!is_zebra_valid_kernel_table(table) && !is_zebra_main_routing_table(table)) @@ -331,8 +340,7 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl, struct rtattr *mxrta[RTAX_MAX + 1]; memset(mxrta, 0, sizeof mxrta); - netlink_parse_rtattr(mxrta, RTAX_MAX, - RTA_DATA(tb[RTA_METRICS]), + netlink_parse_rtattr(mxrta, RTAX_MAX, RTA_DATA(tb[RTA_METRICS]), RTA_PAYLOAD(tb[RTA_METRICS])); if (mxrta[RTAX_MTU]) @@ -383,19 +391,20 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl, */ if (proto == ZEBRA_ROUTE_KERNEL) { distance = (metric >> 24) & 0xFF; - metric = (metric & 0x00FFFFFF); + metric = (metric & 0x00FFFFFF); } if (IS_ZEBRA_DEBUG_KERNEL) { char buf[PREFIX_STRLEN]; char buf2[PREFIX_STRLEN]; - zlog_debug( - "%s %s%s%s vrf %u metric: %d Admin Distance: %d", nl_msg_type_to_str(h->nlmsg_type), - prefix2str(&p, buf, sizeof(buf)), - src_p.prefixlen ? " from " : "", - src_p.prefixlen ? prefix2str(&src_p, buf2, sizeof(buf2)) - : "", - vrf_id, metric, distance); + zlog_debug("%s %s%s%s vrf %u metric: %d Admin Distance: %d", + nl_msg_type_to_str(h->nlmsg_type), + prefix2str(&p, buf, sizeof(buf)), + src_p.prefixlen ? " from " : "", + src_p.prefixlen + ? prefix2str(&src_p, buf2, sizeof(buf2)) + : "", + vrf_id, metric, distance); } afi_t afi = AFI_IP; @@ -416,9 +425,10 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl, if (index && !gate) nh.type = NEXTHOP_TYPE_IFINDEX; else if (index && gate) - nh.type = (afi == AFI_IP) - ? NEXTHOP_TYPE_IPV4_IFINDEX - : NEXTHOP_TYPE_IPV6_IFINDEX; + nh.type = + (afi == AFI_IP) + ? NEXTHOP_TYPE_IPV4_IFINDEX + : NEXTHOP_TYPE_IPV6_IFINDEX; else if (!index && gate) nh.type = (afi == AFI_IP) ? NEXTHOP_TYPE_IPV4 @@ -438,8 +448,7 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl, memcpy(&nh.gate, gate, sz); if (index) { - ifp = if_lookup_by_index(index, - VRF_UNKNOWN); + ifp = if_lookup_by_index(index, VRF_UNKNOWN); if (ifp) nh_vrf_id = ifp->vrf_id; } @@ -544,8 +553,8 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl, if (re->nexthop_num == 0) XFREE(MTYPE_RE, re); else - rib_add_multipath(afi, SAFI_UNICAST, &p, - NULL, re); + rib_add_multipath(afi, SAFI_UNICAST, &p, NULL, + re); } } else { if (!tb[RTA_MULTIPATH]) { @@ -576,15 +585,13 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl, nh.ifindex = index; if (gate) memcpy(&nh.gate, gate, sz); - rib_delete(afi, SAFI_UNICAST, vrf_id, - proto, 0, flags, &p, NULL, &nh, - table, metric, true, NULL); + rib_delete(afi, SAFI_UNICAST, vrf_id, proto, 0, flags, + &p, NULL, &nh, table, metric, true, NULL); } else { /* XXX: need to compare the entire list of nexthops * here for NLM_F_APPEND stupidity */ - rib_delete(afi, SAFI_UNICAST, vrf_id, - proto, 0, flags, &p, NULL, NULL, - table, metric, true, NULL); + rib_delete(afi, SAFI_UNICAST, vrf_id, proto, 0, flags, + &p, NULL, NULL, table, metric, true, NULL); } } @@ -609,7 +616,7 @@ static int netlink_route_change_read_multicast(struct sockaddr_nl *snl, char sbuf[40]; char gbuf[40]; char oif_list[256] = "\0"; - vrf_id_t vrf = ns_id; + vrf_id_t vrf; int table; if (mroute) @@ -631,7 +638,7 @@ static int netlink_route_change_read_multicast(struct sockaddr_nl *snl, else table = rtm->rtm_table; - vrf = vrf_lookup_by_table(table); + vrf = vrf_lookup_by_table(table, ns_id); if (tb[RTA_IIF]) iif = *(int *)RTA_DATA(tb[RTA_IIF]); @@ -687,24 +694,23 @@ int netlink_route_change(struct sockaddr_nl *snl, struct nlmsghdr *h, ns_id_t ns_id, int startup) { int len; - vrf_id_t vrf_id = ns_id; struct rtmsg *rtm; rtm = NLMSG_DATA(h); if (!(h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE)) { /* If this is not route add/delete message print warning. */ - zlog_warn("Kernel message: %d vrf %u\n", h->nlmsg_type, vrf_id); + zlog_warn("Kernel message: %d NS %u\n", h->nlmsg_type, ns_id); return 0; } /* Connected route. */ if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug("%s %s %s proto %s vrf %u", + zlog_debug("%s %s %s proto %s NS %u", nl_msg_type_to_str(h->nlmsg_type), nl_family_to_str(rtm->rtm_family), nl_rttype_to_str(rtm->rtm_type), - nl_rtproto_to_str(rtm->rtm_protocol), vrf_id); + nl_rtproto_to_str(rtm->rtm_protocol), ns_id); /* We don't care about change notifications for the MPLS table. */ /* TODO: Revisit this. */ @@ -1274,7 +1280,7 @@ static void _netlink_mpls_debug(int cmd, u_int32_t label, const char *routedesc) } static int netlink_neigh_update(int cmd, int ifindex, uint32_t addr, char *lla, - int llalen) + int llalen, ns_id_t ns_id) { struct { struct nlmsghdr n; @@ -1282,7 +1288,7 @@ static int netlink_neigh_update(int cmd, int ifindex, uint32_t addr, char *lla, char buf[256]; } req; - struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT); + struct zebra_ns *zns = zebra_ns_lookup(ns_id); memset(&req.n, 0, sizeof(req.n)); memset(&req.ndm, 0, sizeof(req.ndm)); @@ -1326,9 +1332,10 @@ static int netlink_route_multipath(int cmd, struct prefix *p, char buf[NL_PKT_BUF_SIZE]; } req; - struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT); + struct zebra_ns *zns; struct zebra_vrf *zvrf = vrf_info_lookup(re->vrf_id); + zns = zvrf->zns; memset(&req, 0, sizeof req - NL_PKT_BUF_SIZE); bytelen = (family == AF_INET ? 4 : 16); @@ -1391,11 +1398,10 @@ static int netlink_route_multipath(int cmd, struct prefix *p, /* Count overall nexthops so we can decide whether to use singlepath * or multipath case. */ nexthop_num = 0; - for (ALL_NEXTHOPS(re->nexthop, nexthop)) { + for (ALL_NEXTHOPS(re->ng, nexthop)) { if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) continue; - if (cmd == RTM_NEWROUTE - && !NEXTHOP_IS_ACTIVE(nexthop->flags)) + if (cmd == RTM_NEWROUTE && !NEXTHOP_IS_ACTIVE(nexthop->flags)) continue; if (cmd == RTM_DELROUTE && !CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)) @@ -1407,7 +1413,7 @@ static int netlink_route_multipath(int cmd, struct prefix *p, /* Singlepath case. */ if (nexthop_num == 1 || multipath_num == 1) { nexthop_num = 0; - for (ALL_NEXTHOPS(re->nexthop, nexthop)) { + for (ALL_NEXTHOPS(re->ng, nexthop)) { /* * So we want to cover 2 types of blackhole * routes here: @@ -1507,7 +1513,7 @@ static int netlink_route_multipath(int cmd, struct prefix *p, rtnh = RTA_DATA(rta); nexthop_num = 0; - for (ALL_NEXTHOPS(re->nexthop, nexthop)) { + for (ALL_NEXTHOPS(re->ng, nexthop)) { if (nexthop_num >= multipath_num) break; @@ -1626,8 +1632,9 @@ int kernel_get_ipmr_sg_stats(struct zebra_vrf *zvrf, void *in) } req; mroute = mr; - struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT); + struct zebra_ns *zns; + zns = zvrf->zns; memset(&req.n, 0, sizeof(req.n)); memset(&req.ndm, 0, sizeof(req.ndm)); @@ -1677,15 +1684,14 @@ void kernel_route_rib(struct route_node *rn, struct prefix *p, * screwed. */ if (old) - netlink_route_multipath(RTM_DELROUTE, p, - src_p, old, 0); - ret = netlink_route_multipath(RTM_NEWROUTE, p, - src_p, new, 0); + netlink_route_multipath(RTM_DELROUTE, p, src_p, + old, 0); + ret = netlink_route_multipath(RTM_NEWROUTE, p, src_p, + new, 0); } kernel_route_rib_pass_fail(rn, p, new, - (!ret) ? - SOUTHBOUND_INSTALL_SUCCESS : - SOUTHBOUND_INSTALL_FAILURE); + (!ret) ? SOUTHBOUND_INSTALL_SUCCESS + : SOUTHBOUND_INSTALL_FAILURE); return; } @@ -1693,17 +1699,16 @@ void kernel_route_rib(struct route_node *rn, struct prefix *p, ret = netlink_route_multipath(RTM_DELROUTE, p, src_p, old, 0); kernel_route_rib_pass_fail(rn, p, old, - (!ret) ? - SOUTHBOUND_DELETE_SUCCESS : - SOUTHBOUND_DELETE_FAILURE); + (!ret) ? SOUTHBOUND_DELETE_SUCCESS + : SOUTHBOUND_DELETE_FAILURE); } } int kernel_neigh_update(int add, int ifindex, uint32_t addr, char *lla, - int llalen) + int llalen, ns_id_t ns_id) { return netlink_neigh_update(add ? RTM_NEWNEIGH : RTM_DELNEIGH, ifindex, - addr, lla, llalen); + addr, lla, llalen, ns_id); } /* @@ -1713,14 +1718,16 @@ int kernel_neigh_update(int add, int ifindex, uint32_t addr, char *lla, static int netlink_vxlan_flood_list_update(struct interface *ifp, struct in_addr *vtep_ip, int cmd) { - struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT); + struct zebra_ns *zns; struct { struct nlmsghdr n; struct ndmsg ndm; char buf[256]; } req; u_char dst_mac[6] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; + struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(ifp->vrf_id); + zns = zvrf->zns; memset(&req.n, 0, sizeof(req.n)); memset(&req.ndm, 0, sizeof(req.ndm)); @@ -1776,7 +1783,7 @@ int kernel_del_vtep(vni_t vni, struct interface *ifp, struct in_addr *vtep_ip) #endif static int netlink_macfdb_change(struct sockaddr_nl *snl, struct nlmsghdr *h, - int len) + int len, ns_id_t ns_id) { struct ndmsg *ndm; struct interface *ifp; @@ -1799,7 +1806,7 @@ static int netlink_macfdb_change(struct sockaddr_nl *snl, struct nlmsghdr *h, return 0; /* The interface should exist. */ - ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT), + ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(ns_id), ndm->ndm_ifindex); if (!ifp || !ifp->info) return 0; @@ -1930,7 +1937,7 @@ static int netlink_macfdb_table(struct sockaddr_nl *snl, struct nlmsghdr *h, if (ndm->ndm_family != AF_BRIDGE) return 0; - return netlink_macfdb_change(snl, h, len); + return netlink_macfdb_change(snl, h, len, ns_id); } /* Request for MAC FDB information from the kernel */ @@ -2012,7 +2019,7 @@ static int netlink_macfdb_update(struct interface *ifp, vlanid_t vid, struct ethaddr *mac, struct in_addr vtep_ip, int local, int cmd, u_char sticky) { - struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT); + struct zebra_ns *zns; struct { struct nlmsghdr n; struct ndmsg ndm; @@ -2026,7 +2033,9 @@ static int netlink_macfdb_update(struct interface *ifp, vlanid_t vid, int vid_present = 0, dst_present = 0; char vid_buf[20]; char dst_buf[30]; + struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(ifp->vrf_id); + zns = zvrf->zns; zif = ifp->info; if ((br_if = zif->brslave_info.br_if) == NULL) { zlog_warn("MAC %s on IF %s(%u) - no mapping to bridge", @@ -2086,7 +2095,7 @@ static int netlink_macfdb_update(struct interface *ifp, vlanid_t vid, | NUD_DELAY) static int netlink_ipneigh_change(struct sockaddr_nl *snl, struct nlmsghdr *h, - int len) + int len, ns_id_t ns_id) { struct ndmsg *ndm; struct interface *ifp; @@ -2107,7 +2116,7 @@ static int netlink_ipneigh_change(struct sockaddr_nl *snl, struct nlmsghdr *h, return 0; /* The interface should exist. */ - ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT), + ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(ns_id), ndm->ndm_ifindex); if (!ifp || !ifp->info) return 0; @@ -2129,7 +2138,7 @@ static int netlink_ipneigh_change(struct sockaddr_nl *snl, struct nlmsghdr *h, * itself */ if (IS_ZEBRA_IF_VLAN(ifp)) { - link_if = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT), + link_if = if_lookup_by_index_per_ns(zebra_ns_lookup(ns_id), zif->link_ifindex); if (!link_if) return 0; @@ -2162,7 +2171,8 @@ static int netlink_ipneigh_change(struct sockaddr_nl *snl, struct nlmsghdr *h, nl_msg_type_to_str(h->nlmsg_type), nl_family_to_str(ndm->ndm_family), ifp->name, ndm->ndm_ifindex, - (unsigned long)RTA_PAYLOAD(tb[NDA_LLADDR])); + (unsigned long)RTA_PAYLOAD( + tb[NDA_LLADDR])); return 0; } @@ -2307,13 +2317,13 @@ int netlink_neigh_change(struct sockaddr_nl *snl, struct nlmsghdr *h, /* Is this a notification for the MAC FDB or IP neighbor table? */ ndm = NLMSG_DATA(h); if (ndm->ndm_family == AF_BRIDGE) - return netlink_macfdb_change(snl, h, len); + return netlink_macfdb_change(snl, h, len, ns_id); if (ndm->ndm_type != RTN_UNICAST) return 0; if (ndm->ndm_family == AF_INET || ndm->ndm_family == AF_INET6) - return netlink_ipneigh_change(snl, h, len); + return netlink_ipneigh_change(snl, h, len, ns_id); return 0; } @@ -2328,10 +2338,12 @@ static int netlink_neigh_update2(struct interface *ifp, struct ipaddr *ip, } req; int ipa_len; - struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT); + struct zebra_ns *zns; char buf[INET6_ADDRSTRLEN]; char buf2[ETHER_ADDR_STRLEN]; + struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(ifp->vrf_id); + zns = zvrf->zns; memset(&req.n, 0, sizeof(req.n)); memset(&req.ndm, 0, sizeof(req.ndm)); |
