diff options
Diffstat (limited to 'extras/router-plugin/devices/rtnetlink/netns.c')
-rw-r--r-- | extras/router-plugin/devices/rtnetlink/netns.c | 935 |
1 files changed, 494 insertions, 441 deletions
diff --git a/extras/router-plugin/devices/rtnetlink/netns.c b/extras/router-plugin/devices/rtnetlink/netns.c index 19adb469a..0d9986185 100644 --- a/extras/router-plugin/devices/rtnetlink/netns.c +++ b/extras/router-plugin/devices/rtnetlink/netns.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -13,190 +13,197 @@ * limitations under the License. */ - -#include <vlib/vlib.h> +#include <stddef.h> #include <vlib/unix/unix.h> +#include <vlib/vlib.h> #include <vnet/ethernet/ethernet.h> +#include <vnet/ip/format.h> #include <vnet/ip/ip4_packet.h> #include <vnet/ip/ip6_packet.h> -#include <vnet/ip/format.h> -#include <stddef.h> #include "netns.h" +#include <hicn/util/sstrncpy.h> /* Enable some RTA values debug */ //#define RTNL_CHECK -#define is_nonzero(x) \ - ({ \ - u8 __is_zero_zero[sizeof(x)] = {}; \ - memcmp(__is_zero_zero, &x, sizeof(x)); \ +#define is_nonzero(x) \ + ({ \ + u8 __is_zero_zero[sizeof (x)] = {}; \ + memcmp (__is_zero_zero, &x, sizeof (x)); \ }) -typedef struct { - u8 type; //Attribute identifier - u8 unique; //Part of the values uniquely identifying an entry - u16 offset; //Offset where stored in struct - u16 size; //Length of the attribute +typedef struct +{ + u8 type; // Attribute identifier + u8 unique; // Part of the values uniquely identifying an entry + u16 offset; // Offset where stored in struct + u16 size; // Length of the attribute } rtnl_mapping_t; -#define ns_foreach_ifla \ - _(IFLA_ADDRESS, hwaddr) \ - _(IFLA_BROADCAST, broadcast) \ - _(IFLA_IFNAME, ifname) \ - _(IFLA_MASTER, master) \ - _(IFLA_MTU, mtu) \ - _(IFLA_QDISC, qdisc) +#define ns_foreach_ifla \ + _ (IFLA_ADDRESS, hwaddr) \ + _ (IFLA_BROADCAST, broadcast) \ + _ (IFLA_IFNAME, ifname) \ + _ (IFLA_MASTER, master) \ + _ (IFLA_MTU, mtu) \ + _ (IFLA_QDISC, qdisc) static rtnl_mapping_t ns_ifmap[] = { -#define _(t, e) \ - { \ - .type = t, \ - .offset = offsetof(ns_link_t, e), \ - .size = sizeof(((ns_link_t*)0)->e) \ - }, +#define _(t, e) \ + { .type = t, \ + .offset = offsetof (ns_link_t, e), \ + .size = sizeof (((ns_link_t *) 0)->e) }, ns_foreach_ifla #undef _ { .type = 0 } }; -u8 *format_ns_link (u8 *s, va_list *args) +u8 * +format_ns_link (u8 *s, va_list *args) { - ns_link_t *l = va_arg(*args, ns_link_t *); - s = format(s, "%s index %u", l->ifname, l->ifi.ifi_index); + ns_link_t *l = va_arg (*args, ns_link_t *); + s = format (s, "%s index %u", l->ifname, l->ifi.ifi_index); return s; } -#define ns_foreach_rta \ - _(RTA_DST, dst, 1) \ - _(RTA_SRC, src, 1) \ - _(RTA_GATEWAY, gateway, 1) \ - _(RTA_IIF, iif, 1) \ - _(RTA_OIF, oif, 1) \ - _(RTA_PREFSRC, prefsrc, 0) \ - _(RTA_TABLE, table, 0) \ - _(RTA_PRIORITY, priority, 0) \ - _(RTA_CACHEINFO, cacheinfo, 0) \ - _(RTA_ENCAP, encap, 1) +#define ns_foreach_rta \ + _ (RTA_DST, dst, 1) \ + _ (RTA_SRC, src, 1) \ + _ (RTA_GATEWAY, gateway, 1) \ + _ (RTA_IIF, iif, 1) \ + _ (RTA_OIF, oif, 1) \ + _ (RTA_PREFSRC, prefsrc, 0) \ + _ (RTA_TABLE, table, 0) \ + _ (RTA_PRIORITY, priority, 0) \ + _ (RTA_CACHEINFO, cacheinfo, 0) \ + _ (RTA_ENCAP, encap, 1) static rtnl_mapping_t ns_routemap[] = { -#define _(t, e, u) \ - { \ - .type = t, .unique = u, \ - .offset = offsetof(ns_route_t, e), \ - .size = sizeof(((ns_route_t*)0)->e) \ - }, +#define _(t, e, u) \ + { .type = t, \ + .unique = u, \ + .offset = offsetof (ns_route_t, e), \ + .size = sizeof (((ns_route_t *) 0)->e) }, ns_foreach_rta #undef _ { .type = 0 } }; -u8 *format_ns_route (u8 *s, va_list *args) +u8 * +format_ns_route (u8 *s, va_list *args) { - ns_route_t *r = va_arg(*args, ns_route_t *); - void *format_ip = r->rtm.rtm_family == AF_INET ? format_ip4_address : format_ip6_address; - s = format(s, "%U/%d", format_ip, r->dst, r->rtm.rtm_dst_len); + ns_route_t *r = va_arg (*args, ns_route_t *); + void *format_ip = + r->rtm.rtm_family == AF_INET ? format_ip4_address : format_ip6_address; + s = format (s, "%U/%d", format_ip, r->dst, r->rtm.rtm_dst_len); if (r->rtm.rtm_src_len) - s = format(s, " from %U/%d", format_ip, r->src, r->rtm.rtm_src_len); - if (is_nonzero(r->gateway)) - s = format(s, " via %U", format_ip, r->gateway); + s = format (s, " from %U/%d", format_ip, r->src, r->rtm.rtm_src_len); + if (is_nonzero (r->gateway)) + s = format (s, " via %U", format_ip, r->gateway); if (r->iif) - s = format(s, " iif %d", r->iif); + s = format (s, " iif %d", r->iif); if (r->oif) - s = format(s, " oif %d", r->oif); - if (is_nonzero(r->prefsrc)) - s = format(s, " src %U", format_ip, r->prefsrc); + s = format (s, " oif %d", r->oif); + if (is_nonzero (r->prefsrc)) + s = format (s, " src %U", format_ip, r->prefsrc); if (r->table) - s = format(s, " table %d", r->table); + s = format (s, " table %d", r->table); if (r->priority) - s = format(s, " priority %u", r->priority); + s = format (s, " priority %u", r->priority); return s; } -#define ns_foreach_ifaddr \ - _(IFA_ADDRESS, addr, 1) \ - _(IFA_LOCAL, local, 1) \ - _(IFA_LABEL, label, 0) \ - _(IFA_BROADCAST, broadcast, 0) \ - _(IFA_ANYCAST, anycast, 0) \ - _(IFA_CACHEINFO, cacheinfo, 0) +#define ns_foreach_ifaddr \ + _ (IFA_ADDRESS, addr, 1) \ + _ (IFA_LOCAL, local, 1) \ + _ (IFA_LABEL, label, 0) \ + _ (IFA_BROADCAST, broadcast, 0) \ + _ (IFA_ANYCAST, anycast, 0) \ + _ (IFA_CACHEINFO, cacheinfo, 0) static rtnl_mapping_t ns_addrmap[] = { -#define _(t, e, u) \ - { \ - .type = t, .unique = u, \ - .offset = offsetof(ns_addr_t, e), \ - .size = sizeof(((ns_addr_t*)0)->e) \ - }, +#define _(t, e, u) \ + { .type = t, \ + .unique = u, \ + .offset = offsetof (ns_addr_t, e), \ + .size = sizeof (((ns_addr_t *) 0)->e) }, ns_foreach_ifaddr #undef _ { .type = 0 } }; -u8 *format_ns_addr (u8 *s, va_list *args) -{ - ns_addr_t *a = va_arg(*args, ns_addr_t *); - void *format_ip = a->ifaddr.ifa_family == AF_INET ? format_ip4_address : format_ip6_address; - s = format(s, "%U/%d", format_ip, a->addr, a->ifaddr.ifa_prefixlen); - if (is_nonzero(a->label)) - s = format(s, " dev %s", a->label); - if (is_nonzero(a->broadcast)) - s = format(s, " broadcast %U", format_ip, a->broadcast); - if (is_nonzero(a->anycast)) - s = format(s, " anycast %U", format_ip, a->anycast); - if (is_nonzero(a->local)) - s = format(s, " local %U", format_ip, a->local); +u8 * +format_ns_addr (u8 *s, va_list *args) +{ + ns_addr_t *a = va_arg (*args, ns_addr_t *); + void *format_ip = + a->ifaddr.ifa_family == AF_INET ? format_ip4_address : format_ip6_address; + s = format (s, "%U/%d", format_ip, a->addr, a->ifaddr.ifa_prefixlen); + if (is_nonzero (a->label)) + s = format (s, " dev %s", a->label); + if (is_nonzero (a->broadcast)) + s = format (s, " broadcast %U", format_ip, a->broadcast); + if (is_nonzero (a->anycast)) + s = format (s, " anycast %U", format_ip, a->anycast); + if (is_nonzero (a->local)) + s = format (s, " local %U", format_ip, a->local); return s; } #ifndef NDA_RTA -#define NDA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg)))) -#define NDA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ndmsg)) +#define NDA_RTA(r) \ + ((struct rtattr *) (((char *) (r)) + NLMSG_ALIGN (sizeof (struct ndmsg)))) +#define NDA_PAYLOAD(n) NLMSG_PAYLOAD (n, sizeof (struct ndmsg)) #endif -#define ns_foreach_neigh \ - _(NDA_DST, dst, 1) \ - _(NDA_LLADDR, lladdr, 0) \ - _(NDA_PROBES, probes, 0) \ - _(NDA_CACHEINFO, cacheinfo, 0) +#define ns_foreach_neigh \ + _ (NDA_DST, dst, 1) \ + _ (NDA_LLADDR, lladdr, 0) \ + _ (NDA_PROBES, probes, 0) \ + _ (NDA_CACHEINFO, cacheinfo, 0) static rtnl_mapping_t ns_neighmap[] = { -#define _(t, e, u) \ - { \ - .type = t, .unique = u, \ - .offset = offsetof(ns_neigh_t, e), \ - .size = sizeof(((ns_neigh_t*)0)->e) \ - }, +#define _(t, e, u) \ + { .type = t, \ + .unique = u, \ + .offset = offsetof (ns_neigh_t, e), \ + .size = sizeof (((ns_neigh_t *) 0)->e) }, ns_foreach_neigh #undef _ { .type = 0 } }; -u8 *format_ns_neigh (u8 *s, va_list *args) +u8 * +format_ns_neigh (u8 *s, va_list *args) { - ns_neigh_t *n = va_arg(*args, ns_neigh_t *); - void *format_ip = n->nd.ndm_family == AF_INET ? format_ip4_address : format_ip6_address; - s = format(s, "%U", format_ip, n->dst); - if (is_nonzero(n->lladdr)) - s = format(s, " lladdr %U", format_ethernet_address, n->lladdr); + ns_neigh_t *n = va_arg (*args, ns_neigh_t *); + void *format_ip = + n->nd.ndm_family == AF_INET ? format_ip4_address : format_ip6_address; + s = format (s, "%U", format_ip, n->dst); + if (is_nonzero (n->lladdr)) + s = format (s, " lladdr %U", format_ethernet_address, n->lladdr); if (n->probes) - s = format(s, " probes %d", n->probes); + s = format (s, " probes %d", n->probes); return s; } -typedef struct { - void (*notify)(void *obj, netns_type_t type, u32 flags, uword opaque); +typedef struct +{ + void (*notify) (void *obj, netns_type_t type, u32 flags, uword opaque); uword opaque; u32 netns_index; } netns_handle_t; -typedef struct { +typedef struct +{ netns_t netns; u32 rtnl_handle; u32 subscriber_count; } netns_p; -typedef struct { +typedef struct +{ netns_p *netnss; netns_handle_t *handles; } netns_main_t; @@ -204,22 +211,25 @@ typedef struct { netns_main_t netns_main; static int -rtnl_parse_rtattr(struct rtattr *db[], size_t max, - struct rtattr *rta, size_t len) { - for(; RTA_OK(rta, len); rta = RTA_NEXT(rta, len)) { - if (rta->rta_type <= max) - db[rta->rta_type] = rta; +rtnl_parse_rtattr (struct rtattr *db[], size_t max, struct rtattr *rta, + size_t len) +{ + for (; RTA_OK (rta, len); rta = RTA_NEXT (rta, len)) + { + if (rta->rta_type <= max) + db[rta->rta_type] = rta; #ifdef RTNL_CHECK - else - clib_warning("RTA type too high: %d", rta->rta_type); + else + clib_warning ("RTA type too high: %d", rta->rta_type); #endif - } + } - if(len) { - clib_warning("rattr lenght mistmatch %d %d len", - (int) len, (int) rta->rta_len); - return -1; - } + if (len) + { + clib_warning ("rattr lenght mistmatch %d %d len", (int) len, + (int) rta->rta_len); + return -1; + } return 0; } @@ -230,24 +240,24 @@ rtnl_parse_rtattr(struct rtattr *db[], size_t max, */ #ifdef RTNL_CHECK static void -rtnl_entry_check(struct rtattr *rtas[], - size_t rta_len, - rtnl_mapping_t map[], - char *logstr) +rtnl_entry_check (struct rtattr *rtas[], size_t rta_len, rtnl_mapping_t map[], + char *logstr) { int i; - for (i=0; i<rta_len; i++) { - if (!rtas[i]) - continue; - - rtnl_mapping_t *m = map; - for (m = map; m->type; m++) { - if (m->type == rtas[i]->rta_type) - break; + for (i = 0; i < rta_len; i++) + { + if (!rtas[i]) + continue; + + rtnl_mapping_t *m = map; + for (m = map; m->type; m++) + { + if (m->type == rtas[i]->rta_type) + break; + } + if (!m->type) + clib_warning ("Unknown RTA type %d (%s)", rtas[i]->rta_type, logstr); } - if (!m->type) - clib_warning("Unknown RTA type %d (%s)", rtas[i]->rta_type, logstr); - } } #endif @@ -255,433 +265,469 @@ rtnl_entry_check(struct rtattr *rtas[], * Check if the provided entry matches the parsed and unique rtas */ static int -rtnl_entry_match(void *entry, - struct rtattr *rtas[], - rtnl_mapping_t map[]) +rtnl_entry_match (void *entry, struct rtattr *rtas[], rtnl_mapping_t map[]) { u8 zero[1024] = {}; - for ( ;map->type != 0; map++) { - struct rtattr *rta = rtas[map->type]; - size_t rta_len = rta?RTA_PAYLOAD(rta):0; - if (!map->unique) - continue; - - if (rta && RTA_PAYLOAD(rta) > map->size) { - clib_warning("rta (type=%d len=%d) too long (max %d)", - rta->rta_type, rta->rta_len, map->size); - return -1; - } - - if ((rta && memcmp(RTA_DATA(rta), entry + map->offset, rta_len)) || - memcmp(entry + map->offset + rta_len, zero, map->size - rta_len)) { - return 0; + for (; map->type != 0; map++) + { + struct rtattr *rta = rtas[map->type]; + size_t rta_len = rta ? RTA_PAYLOAD (rta) : 0; + if (!map->unique) + continue; + + if (rta && RTA_PAYLOAD (rta) > map->size) + { + clib_warning ("rta (type=%d len=%d) too long (max %d)", + rta->rta_type, rta->rta_len, map->size); + return -1; + } + + if ((rta && memcmp (RTA_DATA (rta), entry + map->offset, rta_len)) || + memcmp (entry + map->offset + rta_len, zero, map->size - rta_len)) + { + return 0; + } } - } return 1; } static int -rtnl_entry_set(void *entry, - struct rtattr *rtas[], - rtnl_mapping_t map[], - int init) -{ - for (; map->type != 0; map++) { - - struct rtattr *rta = rtas[map->type]; - - if(map->type == RTA_ENCAP && rta) { - /*Data of RTA_ENCAP is a pointer to rta attributes for MPLS*/ - rta = (struct rtattr*)RTA_DATA(rta); - if (RTA_PAYLOAD(rta) > map->size) { - clib_warning("rta (type=%d len=%d) too long (max %d)", rta->rta_type, rta->rta_len, map->size); - return -1; - } - memcpy(entry + map->offset, RTA_DATA(rta), map->size); - memset(entry + map->offset + map->size, 0, 0); - } else if (rta) { - if (RTA_PAYLOAD(rta) > map->size) { - clib_warning("rta (type=%d len=%d) too long (max %d)", rta->rta_type, rta->rta_len, map->size); - return -1; - } - memcpy(entry + map->offset, RTA_DATA(rta), RTA_PAYLOAD(rta)); - memset(entry + map->offset + RTA_PAYLOAD(rta), 0, map->size - RTA_PAYLOAD(rta)); - } else if (init) { - memset(entry + map->offset, 0, map->size); +rtnl_entry_set (void *entry, struct rtattr *rtas[], rtnl_mapping_t map[], + int init) +{ + for (; map->type != 0; map++) + { + + struct rtattr *rta = rtas[map->type]; + + if (map->type == RTA_ENCAP && rta) + { + /*Data of RTA_ENCAP is a pointer to rta attributes for MPLS*/ + rta = (struct rtattr *) RTA_DATA (rta); + if (RTA_PAYLOAD (rta) > map->size) + { + clib_warning ("rta (type=%d len=%d) too long (max %d)", + rta->rta_type, rta->rta_len, map->size); + return -1; + } + memcpy (entry + map->offset, RTA_DATA (rta), map->size); + memset (entry + map->offset + map->size, 0, 0); + } + else if (rta) + { + if (RTA_PAYLOAD (rta) > map->size) + { + clib_warning ("rta (type=%d len=%d) too long (max %d)", + rta->rta_type, rta->rta_len, map->size); + return -1; + } + memcpy (entry + map->offset, RTA_DATA (rta), RTA_PAYLOAD (rta)); + memset (entry + map->offset + RTA_PAYLOAD (rta), 0, + map->size - RTA_PAYLOAD (rta)); + } + else if (init) + { + memset (entry + map->offset, 0, map->size); + } } - } return 0; } void -netns_notify(netns_p *ns, void *obj, netns_type_t type, u32 flags) +netns_notify (netns_p *ns, void *obj, netns_type_t type, u32 flags) { netns_main_t *nm = &netns_main; netns_handle_t *h; - pool_foreach(h, nm->handles, { - if (h->netns_index == (ns - nm->netnss) && h->notify) - h->notify(obj, type, flags, h->opaque); - }); + pool_foreach (h, nm->handles, { + if (h->netns_index == (ns - nm->netnss) && h->notify) + h->notify (obj, type, flags, h->opaque); + }) + ; } static_always_inline int -mask_match(void *a, void *b, void *mask, size_t len) +mask_match (void *a, void *b, void *mask, size_t len) { u8 *va = (u8 *) a; u8 *vb = (u8 *) b; u8 *vm = (u8 *) mask; - while (len--) { - if ((va[len] ^ vb[len]) & vm[len]) - return 0; - } + while (len--) + { + if ((va[len] ^ vb[len]) & vm[len]) + return 0; + } return 1; } static ns_link_t * -ns_get_link(netns_p *ns, struct ifinfomsg *ifi, struct rtattr *rtas[]) +ns_get_link (netns_p *ns, struct ifinfomsg *ifi, struct rtattr *rtas[]) { ns_link_t *link; - pool_foreach(link, ns->netns.links, { - if(ifi->ifi_index == link->ifi.ifi_index) - return link; - }); + pool_foreach (link, ns->netns.links, { + if (ifi->ifi_index == link->ifi.ifi_index) + return link; + }) + ; return NULL; } static int -ns_rcv_link(netns_p *ns, struct nlmsghdr *hdr) +ns_rcv_link (netns_p *ns, struct nlmsghdr *hdr) { ns_link_t *link; struct ifinfomsg *ifi; struct rtattr *rtas[IFLA_MAX + 1] = {}; - size_t datalen = hdr->nlmsg_len - NLMSG_ALIGN(sizeof(*hdr)); + size_t datalen = hdr->nlmsg_len - NLMSG_ALIGN (sizeof (*hdr)); - if(datalen < sizeof(*ifi)) + if (datalen < sizeof (*ifi)) return -1; - ifi = NLMSG_DATA(hdr); - if((datalen > NLMSG_ALIGN(sizeof(*ifi))) && - rtnl_parse_rtattr(rtas, IFLA_MAX, IFLA_RTA(ifi), - IFLA_PAYLOAD(hdr))) { - return -1; - } + ifi = NLMSG_DATA (hdr); + if ((datalen > NLMSG_ALIGN (sizeof (*ifi))) && + rtnl_parse_rtattr (rtas, IFLA_MAX, IFLA_RTA (ifi), IFLA_PAYLOAD (hdr))) + { + return -1; + } #ifdef RTNL_CHECK - rtnl_entry_check(rtas, IFLA_MAX + 1, ns_ifmap, "link"); + rtnl_entry_check (rtas, IFLA_MAX + 1, ns_ifmap, "link"); #endif - link = ns_get_link(ns, ifi, rtas); + link = ns_get_link (ns, ifi, rtas); - if (hdr->nlmsg_type == RTM_DELLINK) { - if (!link) - return -1; - pool_put(ns->netns.links, link); - netns_notify(ns, link, NETNS_TYPE_LINK, NETNS_F_DEL); - return 0; - } - - if (!link) { - pool_get(ns->netns.links, link); - rtnl_entry_set(link, rtas, ns_ifmap, 1); - } else { - rtnl_entry_set(link, rtas, ns_ifmap, 0); - } + if (hdr->nlmsg_type == RTM_DELLINK) + { + if (!link) + return -1; + pool_put (ns->netns.links, link); + netns_notify (ns, link, NETNS_TYPE_LINK, NETNS_F_DEL); + return 0; + } + + if (!link) + { + pool_get (ns->netns.links, link); + rtnl_entry_set (link, rtas, ns_ifmap, 1); + } + else + { + rtnl_entry_set (link, rtas, ns_ifmap, 0); + } link->ifi = *ifi; - link->last_updated = vlib_time_now(vlib_get_main()); - netns_notify(ns, link, NETNS_TYPE_LINK, NETNS_F_ADD); + link->last_updated = vlib_time_now (vlib_get_main ()); + netns_notify (ns, link, NETNS_TYPE_LINK, NETNS_F_ADD); return 0; } static ns_route_t * -ns_get_route(netns_p *ns, struct rtmsg *rtm, struct rtattr *rtas[]) +ns_get_route (netns_p *ns, struct rtmsg *rtm, struct rtattr *rtas[]) { ns_route_t *route; - //This describes the values which uniquely identify a route - struct rtmsg msg = { - .rtm_family = 0xff, - .rtm_dst_len = 0xff, - .rtm_src_len = 0xff, - .rtm_table = 0xff, - .rtm_protocol = 0xff, - .rtm_type = 0xff - }; - - pool_foreach(route, ns->netns.routes, { - if(mask_match(&route->rtm, rtm, &msg, sizeof(struct rtmsg)) && - rtnl_entry_match(route, rtas, ns_routemap)) - return route; - }); + // This describes the values which uniquely identify a route + struct rtmsg msg = { .rtm_family = 0xff, + .rtm_dst_len = 0xff, + .rtm_src_len = 0xff, + .rtm_table = 0xff, + .rtm_protocol = 0xff, + .rtm_type = 0xff }; + + pool_foreach (route, ns->netns.routes, { + if (mask_match (&route->rtm, rtm, &msg, sizeof (struct rtmsg)) && + rtnl_entry_match (route, rtas, ns_routemap)) + return route; + }) + ; return NULL; } static int -ns_rcv_route(netns_p *ns, struct nlmsghdr *hdr) +ns_rcv_route (netns_p *ns, struct nlmsghdr *hdr) { ns_route_t *route; struct rtmsg *rtm; struct rtattr *rtas[RTA_MAX + 1] = {}; - size_t datalen = hdr->nlmsg_len - NLMSG_ALIGN(sizeof(*hdr)); + size_t datalen = hdr->nlmsg_len - NLMSG_ALIGN (sizeof (*hdr)); - if(datalen < sizeof(*rtm)) + if (datalen < sizeof (*rtm)) return -1; - rtm = NLMSG_DATA(hdr); - if((datalen > NLMSG_ALIGN(sizeof(*rtm))) && - rtnl_parse_rtattr(rtas, RTA_MAX, RTM_RTA(rtm), - RTM_PAYLOAD(hdr))) { - return -1; - } + rtm = NLMSG_DATA (hdr); + if ((datalen > NLMSG_ALIGN (sizeof (*rtm))) && + rtnl_parse_rtattr (rtas, RTA_MAX, RTM_RTA (rtm), RTM_PAYLOAD (hdr))) + { + return -1; + } #ifdef RTNL_CHECK - rtnl_entry_check(rtas, RTA_MAX + 1, ns_routemap, "route"); + rtnl_entry_check (rtas, RTA_MAX + 1, ns_routemap, "route"); #endif - route = ns_get_route(ns, rtm, rtas); + route = ns_get_route (ns, rtm, rtas); + + if (hdr->nlmsg_type == RTM_DELROUTE) + { + if (!route) + return -1; + pool_put (ns->netns.routes, route); + netns_notify (ns, route, NETNS_TYPE_ROUTE, NETNS_F_DEL); + return 0; + } - if (hdr->nlmsg_type == RTM_DELROUTE) { - if (!route) - return -1; - pool_put(ns->netns.routes, route); - netns_notify(ns, route, NETNS_TYPE_ROUTE, NETNS_F_DEL); - return 0; - } - - if (!route) { - pool_get(ns->netns.routes, route); - memset(route, 0, sizeof(*route)); - rtnl_entry_set(route, rtas, ns_routemap, 1); - } else { - rtnl_entry_set(route, rtas, ns_routemap, 0); - } + if (!route) + { + pool_get (ns->netns.routes, route); + memset (route, 0, sizeof (*route)); + rtnl_entry_set (route, rtas, ns_routemap, 1); + } + else + { + rtnl_entry_set (route, rtas, ns_routemap, 0); + } route->rtm = *rtm; - route->last_updated = vlib_time_now(vlib_get_main()); - netns_notify(ns, route, NETNS_TYPE_ROUTE, NETNS_F_ADD); + route->last_updated = vlib_time_now (vlib_get_main ()); + netns_notify (ns, route, NETNS_TYPE_ROUTE, NETNS_F_ADD); return 0; } static ns_addr_t * -ns_get_addr(netns_p *ns, struct ifaddrmsg *ifaddr, struct rtattr *rtas[]) +ns_get_addr (netns_p *ns, struct ifaddrmsg *ifaddr, struct rtattr *rtas[]) { ns_addr_t *addr; - //This describes the values which uniquely identify a route + // This describes the values which uniquely identify a route struct ifaddrmsg msg = { .ifa_family = 0xff, .ifa_prefixlen = 0xff, }; - pool_foreach(addr, ns->netns.addresses, { - if(mask_match(&addr->ifaddr, ifaddr, &msg, sizeof(struct ifaddrmsg)) && - rtnl_entry_match(addr, rtas, ns_addrmap)) - return addr; - }); + pool_foreach (addr, ns->netns.addresses, { + if (mask_match (&addr->ifaddr, ifaddr, &msg, sizeof (struct ifaddrmsg)) && + rtnl_entry_match (addr, rtas, ns_addrmap)) + return addr; + }) + ; return NULL; } static int -ns_rcv_addr(netns_p *ns, struct nlmsghdr *hdr) +ns_rcv_addr (netns_p *ns, struct nlmsghdr *hdr) { ns_addr_t *addr; struct ifaddrmsg *ifaddr; struct rtattr *rtas[IFA_MAX + 1] = {}; - size_t datalen = hdr->nlmsg_len - NLMSG_ALIGN(sizeof(*hdr)); + size_t datalen = hdr->nlmsg_len - NLMSG_ALIGN (sizeof (*hdr)); - if(datalen < sizeof(*ifaddr)) + if (datalen < sizeof (*ifaddr)) return -1; - ifaddr = NLMSG_DATA(hdr); - if((datalen > NLMSG_ALIGN(sizeof(*ifaddr))) && - rtnl_parse_rtattr(rtas, IFA_MAX, IFA_RTA(ifaddr), - IFA_PAYLOAD(hdr))) { - return -1; - } + ifaddr = NLMSG_DATA (hdr); + if ((datalen > NLMSG_ALIGN (sizeof (*ifaddr))) && + rtnl_parse_rtattr (rtas, IFA_MAX, IFA_RTA (ifaddr), IFA_PAYLOAD (hdr))) + { + return -1; + } #ifdef RTNL_CHECK - rtnl_entry_check(rtas, IFA_MAX + 1, ns_addrmap, "addr"); + rtnl_entry_check (rtas, IFA_MAX + 1, ns_addrmap, "addr"); #endif - addr = ns_get_addr(ns, ifaddr, rtas); + addr = ns_get_addr (ns, ifaddr, rtas); + + if (hdr->nlmsg_type == RTM_DELADDR) + { + if (!addr) + return -1; + pool_put (ns->netns.addresses, addr); + netns_notify (ns, addr, NETNS_TYPE_ADDR, NETNS_F_DEL); + return 0; + } - if (hdr->nlmsg_type == RTM_DELADDR) { - if (!addr) - return -1; - pool_put(ns->netns.addresses, addr); - netns_notify(ns, addr, NETNS_TYPE_ADDR, NETNS_F_DEL); - return 0; - } - - if (!addr) { - pool_get(ns->netns.addresses, addr); - memset(addr, 0, sizeof(*addr)); - rtnl_entry_set(addr, rtas, ns_addrmap, 1); - } else { - rtnl_entry_set(addr, rtas, ns_addrmap, 0); - } + if (!addr) + { + pool_get (ns->netns.addresses, addr); + memset (addr, 0, sizeof (*addr)); + rtnl_entry_set (addr, rtas, ns_addrmap, 1); + } + else + { + rtnl_entry_set (addr, rtas, ns_addrmap, 0); + } addr->ifaddr = *ifaddr; - addr->last_updated = vlib_time_now(vlib_get_main()); - netns_notify(ns, addr, NETNS_TYPE_ADDR, NETNS_F_ADD); + addr->last_updated = vlib_time_now (vlib_get_main ()); + netns_notify (ns, addr, NETNS_TYPE_ADDR, NETNS_F_ADD); return 0; } static ns_neigh_t * -ns_get_neigh(netns_p *ns, struct ndmsg *nd, struct rtattr *rtas[]) +ns_get_neigh (netns_p *ns, struct ndmsg *nd, struct rtattr *rtas[]) { ns_neigh_t *neigh; - //This describes the values which uniquely identify a route + // This describes the values which uniquely identify a route struct ndmsg msg = { .ndm_family = 0xff, .ndm_ifindex = 0xff, }; - pool_foreach(neigh, ns->netns.neighbors, { - if(mask_match(&neigh->nd, nd, &msg, sizeof(&msg)) && - rtnl_entry_match(neigh, rtas, ns_neighmap)) - return neigh; - }); + pool_foreach (neigh, ns->netns.neighbors, { + if (mask_match (&neigh->nd, nd, &msg, sizeof (&msg)) && + rtnl_entry_match (neigh, rtas, ns_neighmap)) + return neigh; + }) + ; return NULL; } static int -ns_rcv_neigh(netns_p *ns, struct nlmsghdr *hdr) +ns_rcv_neigh (netns_p *ns, struct nlmsghdr *hdr) { ns_neigh_t *neigh; struct ndmsg *nd; struct rtattr *rtas[NDA_MAX + 1] = {}; - size_t datalen = hdr->nlmsg_len - NLMSG_ALIGN(sizeof(*hdr)); + size_t datalen = hdr->nlmsg_len - NLMSG_ALIGN (sizeof (*hdr)); - if(datalen < sizeof(*nd)) + if (datalen < sizeof (*nd)) return -1; - nd = NLMSG_DATA(hdr); - if((datalen > NLMSG_ALIGN(sizeof(*nd))) && - rtnl_parse_rtattr(rtas, NDA_MAX, NDA_RTA(nd), - NDA_PAYLOAD(hdr))) { - return -1; - } + nd = NLMSG_DATA (hdr); + if ((datalen > NLMSG_ALIGN (sizeof (*nd))) && + rtnl_parse_rtattr (rtas, NDA_MAX, NDA_RTA (nd), NDA_PAYLOAD (hdr))) + { + return -1; + } #ifdef RTNL_CHECK - rtnl_entry_check(rtas, NDA_MAX + 1, ns_neighmap, "nd"); + rtnl_entry_check (rtas, NDA_MAX + 1, ns_neighmap, "nd"); #endif - neigh = ns_get_neigh(ns, nd, rtas); + neigh = ns_get_neigh (ns, nd, rtas); + + if (hdr->nlmsg_type == RTM_DELNEIGH) + { + if (!neigh) + return -1; + pool_put (ns->netns.neighbors, neigh); + netns_notify (ns, neigh, NETNS_TYPE_NEIGH, NETNS_F_DEL); + return 0; + } - if (hdr->nlmsg_type == RTM_DELNEIGH) { - if (!neigh) - return -1; - pool_put(ns->netns.neighbors, neigh); - netns_notify(ns, neigh, NETNS_TYPE_NEIGH, NETNS_F_DEL); - return 0; - } - - if (!neigh) { - pool_get(ns->netns.neighbors, neigh); - memset(neigh, 0, sizeof(*neigh)); - rtnl_entry_set(neigh, rtas, ns_neighmap, 1); - } else { - rtnl_entry_set(neigh, rtas, ns_neighmap, 0); - } + if (!neigh) + { + pool_get (ns->netns.neighbors, neigh); + memset (neigh, 0, sizeof (*neigh)); + rtnl_entry_set (neigh, rtas, ns_neighmap, 1); + } + else + { + rtnl_entry_set (neigh, rtas, ns_neighmap, 0); + } neigh->nd = *nd; - neigh->last_updated = vlib_time_now(vlib_get_main()); - netns_notify(ns, neigh, NETNS_TYPE_NEIGH, NETNS_F_ADD); + neigh->last_updated = vlib_time_now (vlib_get_main ()); + netns_notify (ns, neigh, NETNS_TYPE_NEIGH, NETNS_F_ADD); return 0; } -#define ns_object_foreach \ - _(neighbors, NETNS_TYPE_NEIGH) \ - _(routes, NETNS_TYPE_ROUTE) \ - _(addresses, NETNS_TYPE_ADDR) \ - _(links, NETNS_TYPE_LINK) +#define ns_object_foreach \ + _ (neighbors, NETNS_TYPE_NEIGH) \ + _ (routes, NETNS_TYPE_ROUTE) \ + _ (addresses, NETNS_TYPE_ADDR) \ + _ (links, NETNS_TYPE_LINK) static void -ns_recv_error(rtnl_error_t err, uword o) +ns_recv_error (rtnl_error_t err, uword o) { - //An error was received. Reset everything. + // An error was received. Reset everything. netns_p *ns = &netns_main.netnss[o]; u32 *indexes = 0; u32 *i = 0; -#define _(pool, type) \ - pool_foreach_index(*i, ns->netns.pool, { \ - vec_add1(indexes, *i); \ - }) \ - vec_foreach(i, indexes) { \ - pool_put_index(ns->netns.pool, *i); \ - netns_notify(ns, &ns->netns.pool[*i], type, NETNS_F_DEL); \ - } \ - vec_reset_length(indexes); +#define _(pool, type) \ + pool_foreach_index (*i, ns->netns.pool, { vec_add1 (indexes, *i); }) \ + vec_foreach (i, indexes) \ + { \ + pool_put_index (ns->netns.pool, *i); \ + netns_notify (ns, &ns->netns.pool[*i], type, NETNS_F_DEL); \ + } \ + vec_reset_length (indexes); ns_object_foreach #undef _ - vec_free(indexes); + vec_free (indexes); } static void -ns_recv_rtnl(struct nlmsghdr *hdr, uword o) +ns_recv_rtnl (struct nlmsghdr *hdr, uword o) { netns_p *ns = &netns_main.netnss[o]; - switch (hdr->nlmsg_type) { - case RTM_NEWROUTE: - case RTM_DELROUTE: - ns_rcv_route(ns, hdr); - break; - case RTM_NEWLINK: - case RTM_DELLINK: - ns_rcv_link(ns, hdr); - break; - case RTM_NEWADDR: - case RTM_DELADDR: - ns_rcv_addr(ns, hdr); - break; - case RTM_NEWNEIGH: - case RTM_DELNEIGH: - ns_rcv_neigh(ns, hdr); - break; - default: - clib_warning("unknown rtnl type %d", hdr->nlmsg_type); - break; - } + switch (hdr->nlmsg_type) + { + case RTM_NEWROUTE: + case RTM_DELROUTE: + ns_rcv_route (ns, hdr); + break; + case RTM_NEWLINK: + case RTM_DELLINK: + ns_rcv_link (ns, hdr); + break; + case RTM_NEWADDR: + case RTM_DELADDR: + ns_rcv_addr (ns, hdr); + break; + case RTM_NEWNEIGH: + case RTM_DELNEIGH: + ns_rcv_neigh (ns, hdr); + break; + default: + clib_warning ("unknown rtnl type %d", hdr->nlmsg_type); + break; + } } static void -netns_destroy(netns_p *ns) +netns_destroy (netns_p *ns) { netns_main_t *nm = &netns_main; - rtnl_stream_close(ns->rtnl_handle); - pool_put(nm->netnss, ns); - pool_free(ns->netns.links); - pool_free(ns->netns.addresses); - pool_free(ns->netns.routes); - pool_free(ns->netns.neighbors); + rtnl_stream_close (ns->rtnl_handle); + pool_put (nm->netnss, ns); + pool_free (ns->netns.links); + pool_free (ns->netns.addresses); + pool_free (ns->netns.routes); + pool_free (ns->netns.neighbors); } static netns_p * -netns_get(char *name) +netns_get (char *name) { netns_main_t *nm = &netns_main; netns_p *ns; - pool_foreach(ns, nm->netnss, { - if (!strcmp(name, ns->netns.name)) - return ns; - }); + pool_foreach (ns, nm->netnss, { + if (!strcmp (name, ns->netns.name)) + return ns; + }) + ; - if (strlen(name) > RTNL_NETNS_NAMELEN) + if (strlen (name) > RTNL_NETNS_NAMELEN) return NULL; - pool_get(nm->netnss, ns); + pool_get (nm->netnss, ns); rtnl_stream_t s = { .recv_message = ns_recv_rtnl, .error = ns_recv_error, - .opaque = (uword)(ns - nm->netnss), + .opaque = (uword) (ns - nm->netnss), }; - strcpy(s.name, name); + int rc = strcpy_s (s.name, sizeof (s.name), name); + if (rc != EOK) + return NULL; u32 handle; - if ((handle = rtnl_stream_open(&s)) == ~0) { - pool_put(nm->netnss, ns); - return NULL; - } + if ((handle = rtnl_stream_open (&s)) == ~0) + { + pool_put (nm->netnss, ns); + return NULL; + } - strcpy(ns->netns.name, name); + rc = strcpy_s (ns->netns.name, sizeof (ns->netns.name), name); + if (rc != EOK) + return NULL; ns->netns.addresses = 0; ns->netns.links = 0; ns->netns.neighbors = 0; @@ -691,15 +737,16 @@ netns_get(char *name) return ns; } -u32 netns_open(char *name, netns_sub_t *sub) +u32 +netns_open (char *name, netns_sub_t *sub) { netns_main_t *nm = &netns_main; netns_p *ns; netns_handle_t *p; - if (!(ns = netns_get(name))) + if (!(ns = netns_get (name))) return ~0; - pool_get(nm->handles, p); + pool_get (nm->handles, p); p->netns_index = ns - nm->netnss; p->notify = sub->notify; p->opaque = sub->opaque; @@ -707,76 +754,82 @@ u32 netns_open(char *name, netns_sub_t *sub) return p - nm->handles; } -netns_t *netns_getns(u32 handle) +netns_t * +netns_getns (u32 handle) { netns_main_t *nm = &netns_main; - netns_handle_t *h = pool_elt_at_index(nm->handles, handle); - netns_p *ns = pool_elt_at_index(nm->netnss, h->netns_index); + netns_handle_t *h = pool_elt_at_index (nm->handles, handle); + netns_p *ns = pool_elt_at_index (nm->netnss, h->netns_index); return &ns->netns; } -void netns_close(u32 handle) +void +netns_close (u32 handle) { netns_main_t *nm = &netns_main; - netns_handle_t *h = pool_elt_at_index(nm->handles, handle); - netns_p *ns = pool_elt_at_index(nm->netnss, h->netns_index); - pool_put(h, nm->handles); + netns_handle_t *h = pool_elt_at_index (nm->handles, handle); + netns_p *ns = pool_elt_at_index (nm->netnss, h->netns_index); + pool_put (h, nm->handles); ns->subscriber_count--; if (!ns->subscriber_count) - netns_destroy(ns); + netns_destroy (ns); } -void netns_callme(u32 handle, char del) +void +netns_callme (u32 handle, char del) { netns_main_t *nm = &netns_main; - netns_handle_t *h = pool_elt_at_index(nm->handles, handle); - netns_p *ns = pool_elt_at_index(nm->netnss, h->netns_index); + netns_handle_t *h = pool_elt_at_index (nm->handles, handle); + netns_p *ns = pool_elt_at_index (nm->netnss, h->netns_index); u32 i = 0; if (!h->notify) return; -#define _(pool, type) \ - pool_foreach_index(i, ns->netns.pool, { \ - h->notify(&ns->netns.pool[i], type, \ - del?NETNS_F_DEL:NETNS_F_ADD, h->opaque); \ - }); +#define _(pool, type) \ + pool_foreach_index (i, ns->netns.pool, { \ + h->notify (&ns->netns.pool[i], type, del ? NETNS_F_DEL : NETNS_F_ADD, \ + h->opaque); \ + }) \ + ; ns_object_foreach #undef _ +} +u8 * +format_ns_object (u8 *s, va_list *args) +{ + netns_type_t t = va_arg (*args, netns_type_t); + void *o = va_arg (*args, void *); + switch (t) + { + case NETNS_TYPE_ADDR: + return format (s, "addr %U", format_ns_addr, o); + case NETNS_TYPE_ROUTE: + return format (s, "route %U", format_ns_route, o); + case NETNS_TYPE_LINK: + return format (s, "link %U", format_ns_link, o); + case NETNS_TYPE_NEIGH: + return format (s, "neigh %U", format_ns_neigh, o); } - -u8 *format_ns_object(u8 *s, va_list *args) -{ - netns_type_t t = va_arg(*args, netns_type_t); - void *o = va_arg(*args, void *); - switch (t) { - case NETNS_TYPE_ADDR: - return format(s, "addr %U", format_ns_addr, o); - case NETNS_TYPE_ROUTE: - return format(s, "route %U", format_ns_route, o); - case NETNS_TYPE_LINK: - return format(s, "link %U", format_ns_link, o); - case NETNS_TYPE_NEIGH: - return format(s, "neigh %U", format_ns_neigh, o); - } return s; } -u8 *format_ns_flags(u8 *s, va_list *args) +u8 * +format_ns_flags (u8 *s, va_list *args) { - u32 flags = va_arg(*args, u32); + u32 flags = va_arg (*args, u32); if (flags & NETNS_F_ADD) - s = format(s, "add"); + s = format (s, "add"); else if (flags & NETNS_F_DEL) - s = format(s, "del"); + s = format (s, "del"); else - s = format(s, "mod"); + s = format (s, "mod"); return s; } clib_error_t * -netns_init (vlib_main_t * vm) +netns_init (vlib_main_t *vm) { netns_main_t *nm = &netns_main; nm->netnss = 0; |