Acked-by: Donald Sharp <sha...@cumulusnetworks.com> On Thu, Jun 4, 2015 at 8:10 AM, Nicolas Dichtel <nicolas.dich...@6wind.com> wrote:
> From: Feng Lu <lu.f...@6wind.com> > > This patch lets the netlink sockets work per VRF. > > * The definition of "struct nlsock" is moved into zebra/rib.h. > > * The previous global variables "netlink" and "netlink_cmd" now > become the members of "struct zebra_vrf", and are initialized > in zebra_vrf_alloc(). > > * All relative functions now work for a specific VRF, by adding > a new parameter which specifies the working VRF, except those > functions in which the VRF ID can be obtained from the interface. > > * kernel_init(), interface_list() and route_read() are now also > working per VRF, and moved from main() to zebra_vrf_enable(). > > * A new function kernel_terminate() is added to release the > netlink sockets. It is called from zebra_vrf_disable(). > > * Correct VRF ID, instead of the previous VRF_DEFAULT, are now > passed to the functions of processing interfaces or route > entries. > > Signed-off-by: Feng Lu <lu.f...@6wind.com> > Reviewed-by: Alain Ritoux <alain.rit...@6wind.com> > Signed-off-by: Nicolas Dichtel <nicolas.dich...@6wind.com> > Acked-by: Donald Sharp <sha...@cumulusnetworks.com> > --- > lib/memtypes.c | 1 + > zebra/if_ioctl.c | 9 +- > zebra/if_ioctl_solaris.c | 9 +- > zebra/if_netlink.c | 4 +- > zebra/if_sysctl.c | 10 ++- > zebra/kernel_null.c | 6 +- > zebra/kernel_socket.c | 16 +++- > zebra/main.c | 8 +- > zebra/rib.h | 17 ++++ > zebra/rt_netlink.c | 219 > +++++++++++++++++++++++++++-------------------- > zebra/rt_netlink.h | 4 +- > zebra/rtread_getmsg.c | 6 +- > zebra/rtread_netlink.c | 4 +- > zebra/rtread_sysctl.c | 8 +- > zebra/test_main.c | 7 +- > zebra/zebra_rib.c | 14 +++ > zebra/zserv.h | 7 +- > 17 files changed, 229 insertions(+), 120 deletions(-) > > diff --git a/lib/memtypes.c b/lib/memtypes.c > index 3e599f673238..60f24e6a7915 100644 > --- a/lib/memtypes.c > +++ b/lib/memtypes.c > @@ -85,6 +85,7 @@ struct memory_list memory_list_zebra[] = > { MTYPE_STATIC_IPV6, "Static IPv6 route" }, > { MTYPE_RIB_DEST, "RIB destination" }, > { MTYPE_RIB_TABLE_INFO, "RIB table info" }, > + { MTYPE_NETLINK_NAME, "Netlink name" }, > { -1, NULL }, > }; > > diff --git a/zebra/if_ioctl.c b/zebra/if_ioctl.c > index f357e15447c3..8df877dbaaa1 100644 > --- a/zebra/if_ioctl.c > +++ b/zebra/if_ioctl.c > @@ -29,8 +29,10 @@ > #include "connected.h" > #include "memory.h" > #include "log.h" > +#include "vrf.h" > > #include "zebra/interface.h" > +#include "zebra/rib.h" > > /* Interface looking up using infamous SIOCGIFCONF. */ > static int > @@ -442,8 +444,13 @@ interface_info_ioctl () > > /* Lookup all interface information. */ > void > -interface_list () > +interface_list (struct zebra_vrf *zvrf) > { > + if (zvrf->vrf_id != VRF_DEFAULT) > + { > + zlog_warn ("interface_list: ignore VRF %u", zvrf->vrf_id); > + return; > + } > /* Linux can do both proc & ioctl, ioctl is the only way to get > interface aliases in 2.2 series kernels. */ > #ifdef HAVE_PROC_NET_DEV > diff --git a/zebra/if_ioctl_solaris.c b/zebra/if_ioctl_solaris.c > index fc384ea29a3f..3f33f749af46 100644 > --- a/zebra/if_ioctl_solaris.c > +++ b/zebra/if_ioctl_solaris.c > @@ -30,8 +30,10 @@ > #include "memory.h" > #include "log.h" > #include "privs.h" > +#include "vrf.h" > > #include "zebra/interface.h" > +#include "zebra/rib.h" > > void lifreq_set_name (struct lifreq *, const char *); > int if_get_flags_direct (const char *, uint64_t *, unsigned int af); > @@ -349,8 +351,13 @@ interface_info_ioctl (struct interface *ifp) > > /* Lookup all interface information. */ > void > -interface_list () > +interface_list (struct zebra_vrf *zvrf) > { > + if (zvrf->vrf_id != VRF_DEFAULT) > + { > + zlog_warn ("interface_list: ignore VRF %u", zvrf->vrf_id); > + return; > + } > interface_list_ioctl (AF_INET); > interface_list_ioctl (AF_INET6); > interface_list_ioctl (AF_UNSPEC); > diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c > index 87014160cfb5..245b7b2509d0 100644 > --- a/zebra/if_netlink.c > +++ b/zebra/if_netlink.c > @@ -27,7 +27,7 @@ > > /* Interface information read by netlink. */ > void > -interface_list (void) > +interface_list (struct zebra_vrf *zvrf) > { > - interface_lookup_netlink (); > + interface_lookup_netlink (zvrf); > } > diff --git a/zebra/if_sysctl.c b/zebra/if_sysctl.c > index ffa6927d617e..bb48f61828a9 100644 > --- a/zebra/if_sysctl.c > +++ b/zebra/if_sysctl.c > @@ -30,9 +30,11 @@ > #include "ioctl.h" > #include "log.h" > #include "interface.h" > +#include "vrf.h" > > #include "zebra/rt.h" > #include "zebra/kernel_socket.h" > +#include "zebra/rib.h" > > void > ifstat_update_sysctl (void) > @@ -90,7 +92,7 @@ ifstat_update_sysctl (void) > > /* Interface listing up function using sysctl(). */ > void > -interface_list () > +interface_list (struct zebra_vrf *zvrf) > { > caddr_t ref, buf, end; > size_t bufsiz; > @@ -107,6 +109,12 @@ interface_list () > 0 > }; > > + if (zvrf->vrf_id != VRF_DEFAULT) > + { > + zlog_warn ("interface_list: ignore VRF %u", zvrf->vrf_id); > + return; > + } > + > /* Query buffer size. */ > if (sysctl (mib, MIBSIZ, NULL, &bufsiz, NULL, 0) < 0) > { > diff --git a/zebra/kernel_null.c b/zebra/kernel_null.c > index 4cd43db48753..58d2c3ae758b 100644 > --- a/zebra/kernel_null.c > +++ b/zebra/kernel_null.c > @@ -28,6 +28,7 @@ > #include "zebra/rt.h" > #include "zebra/redistribute.h" > #include "zebra/connected.h" > +#include "zebra/rib.h" > > int kernel_add_ipv4 (struct prefix *a, struct rib *b) { return 0; } > #ifdef HAVE_SYS_WEAK_ALIAS_PRAGMA > @@ -64,9 +65,10 @@ int kernel_address_delete_ipv4 (struct interface *a, > struct connected *b) > return 0; > } > > -void kernel_init (void) { return; } > +void kernel_init (struct zebra_vrf *zvrf) { return; } > +void kernel_terminate (struct zebra_vrf *zvrf) { return; } > #ifdef HAVE_SYS_WEAK_ALIAS_PRAGMA > #pragma weak route_read = kernel_init > #else > -void route_read (void) { return; } > +void route_read (struct zebra_vrf *zvrf) { return; } > #endif > diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c > index 374ca412aef3..fd0d8fd1b656 100644 > --- a/zebra/kernel_socket.c > +++ b/zebra/kernel_socket.c > @@ -38,6 +38,7 @@ > #include "zebra/zserv.h" > #include "zebra/debug.h" > #include "zebra/kernel_socket.h" > +#include "zebra/rib.h" > > extern struct zebra_privs_t zserv_privs; > extern struct zebra_t zebrad; > @@ -1273,8 +1274,11 @@ kernel_read (struct thread *thread) > > /* Make routing socket. */ > static void > -routing_socket (void) > +routing_socket (struct zebra_vrf *zvrf) > { > + if (zvrf->vrf_id != VRF_DEFAULT) > + return; > + > if ( zserv_privs.change (ZPRIVS_RAISE) ) > zlog_err ("routing_socket: Can't raise privileges"); > > @@ -1305,7 +1309,13 @@ routing_socket (void) > /* Exported interface function. This function simply calls > routing_socket (). */ > void > -kernel_init (void) > +kernel_init (struct zebra_vrf *zvrf) > +{ > + routing_socket (zvrf); > +} > + > +void > +kernel_terminate (struct zebra_vrf *zvrf) > { > - routing_socket (); > + return; > } > diff --git a/zebra/main.c b/zebra/main.c > index 08cc247d8a74..c5d1d76c527f 100644 > --- a/zebra/main.c > +++ b/zebra/main.c > @@ -232,6 +232,10 @@ zebra_vrf_enable (vrf_id_t vrf_id, void **info) > #ifdef RTADV > rtadv_init (zvrf); > #endif > + kernel_init (zvrf); > + interface_list (zvrf); > + route_read (zvrf); > + > return 0; > } > > @@ -259,6 +263,7 @@ zebra_vrf_disable (vrf_id_t vrf_id, void **info) > #ifdef RTADV > rtadv_terminate (zvrf); > #endif > + kernel_terminate (zvrf); > > list_delete_all_node (zvrf->rid_all_sorted_list); > list_delete_all_node (zvrf->rid_lo_sorted_list); > @@ -412,9 +417,6 @@ main (int argc, char **argv) > > /* Initialize VRF module, and make kernel routing socket. */ > zebra_vrf_init (); > - kernel_init (); > - interface_list (); > - route_read (); > > #ifdef HAVE_SNMP > zebra_snmp_init (); > diff --git a/zebra/rib.h b/zebra/rib.h > index 99729411fc38..8328f23bb80c 100644 > --- a/zebra/rib.h > +++ b/zebra/rib.h > @@ -355,6 +355,17 @@ struct rtadv > }; > #endif /* RTADV && HAVE_IPV6 */ > > +#ifdef HAVE_NETLINK > +/* Socket interface to kernel */ > +struct nlsock > +{ > + int sock; > + int seq; > + struct sockaddr_nl snl; > + const char *name; > +}; > +#endif > + > /* Routing table instance. */ > struct zebra_vrf > { > @@ -376,6 +387,12 @@ struct zebra_vrf > /* Static route configuration. */ > struct route_table *stable[AFI_MAX][SAFI_MAX]; > > +#ifdef HAVE_NETLINK > + struct nlsock netlink; /* kernel messages */ > + struct nlsock netlink_cmd; /* command channel */ > + struct thread *t_netlink; > +#endif > + > /* 2nd pointer type used primarily to quell a warning on > * ALL_LIST_ELEMENTS_RO > */ > diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c > index cf6ce0cdeb42..0f0f3fed308a 100644 > --- a/zebra/rt_netlink.c > +++ b/zebra/rt_netlink.c > @@ -46,16 +46,6 @@ > > #include "rt_netlink.h" > > -/* Socket interface to kernel */ > -struct nlsock > -{ > - int sock; > - int seq; > - struct sockaddr_nl snl; > - const char *name; > -} netlink = { -1, 0, {0}, "netlink-listen"}, /* kernel messages > */ > - netlink_cmd = { -1, 0, {0}, "netlink-cmd"}; /* command channel > */ > - > static const struct message nlmsg_str[] = { > {RTM_NEWROUTE, "RTM_NEWROUTE"}, > {RTM_DELROUTE, "RTM_DELROUTE"}, > @@ -155,7 +145,7 @@ netlink_recvbuf (struct nlsock *nl, uint32_t newsize) > > /* Make socket for Linux netlink interface. */ > static int > -netlink_socket (struct nlsock *nl, unsigned long groups) > +netlink_socket (struct nlsock *nl, unsigned long groups, vrf_id_t vrf_id) > { > int ret; > struct sockaddr_nl snl; > @@ -169,7 +159,7 @@ netlink_socket (struct nlsock *nl, unsigned long > groups) > return -1; > } > > - sock = socket (AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); > + sock = vrf_socket (AF_NETLINK, SOCK_RAW, NETLINK_ROUTE, vrf_id); > if (sock < 0) > { > zlog (NULL, LOG_ERR, "Can't open %s socket: %s", nl->name, > @@ -273,8 +263,9 @@ netlink_request (int family, int type, struct nlsock > *nl) > /* Receive message from netlink interface and pass those information > to the given function. */ > static int > -netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr > *), > - struct nlsock *nl) > +netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr > *, > + vrf_id_t), > + struct nlsock *nl, struct zebra_vrf *zvrf) > { > int status; > int ret = 0; > @@ -363,7 +354,7 @@ netlink_parse_info (int (*filter) (struct sockaddr_nl > *, struct nlmsghdr *), > } > > /* Deal with errors that occur because of races in link > handling */ > - if (nl == &netlink_cmd > + if (nl == &zvrf->netlink_cmd > && ((msg_type == RTM_DELROUTE && > (-errnum == ENODEV || -errnum == ESRCH)) > || (msg_type == RTM_NEWROUTE && -errnum == EEXIST))) > @@ -393,16 +384,17 @@ netlink_parse_info (int (*filter) (struct > sockaddr_nl *, struct nlmsghdr *), > /* skip unsolicited messages originating from command socket > * linux sets the originators port-id for {NEW|DEL}ADDR > messages, > * so this has to be checked here. */ > - if (nl != &netlink_cmd && h->nlmsg_pid == netlink_cmd.snl.nl_pid > + if (nl != &zvrf->netlink_cmd > + && h->nlmsg_pid == zvrf->netlink_cmd.snl.nl_pid > && (h->nlmsg_type != RTM_NEWADDR && h->nlmsg_type != > RTM_DELADDR)) > { > if (IS_ZEBRA_DEBUG_KERNEL) > zlog_debug ("netlink_parse_info: %s packet comes from %s", > - netlink_cmd.name, nl->name); > + zvrf->netlink_cmd.name, nl->name); > continue; > } > > - error = (*filter) (&snl, h); > + error = (*filter) (&snl, h, zvrf->vrf_id); > if (error < 0) > { > zlog (NULL, LOG_ERR, "%s filter function error", nl->name); > @@ -473,7 +465,8 @@ netlink_interface_update_hw_addr (struct rtattr **tb, > struct interface *ifp) > /* Called from interface_lookup_netlink(). This function is only used > during bootstrap. */ > static int > -netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h) > +netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h, > + vrf_id_t vrf_id) > { > int len; > struct ifinfomsg *ifi; > @@ -509,7 +502,7 @@ netlink_interface (struct sockaddr_nl *snl, struct > nlmsghdr *h) > name = (char *) RTA_DATA (tb[IFLA_IFNAME]); > > /* Add interface. */ > - ifp = if_get_by_name (name); > + ifp = if_get_by_name_vrf (name, vrf_id); > set_ifindex(ifp, ifi->ifi_index); > ifp->flags = ifi->ifi_flags & 0x0000fffff; > ifp->mtu6 = ifp->mtu = *(uint32_t *) RTA_DATA (tb[IFLA_MTU]); > @@ -526,7 +519,8 @@ netlink_interface (struct sockaddr_nl *snl, struct > nlmsghdr *h) > > /* Lookup interface IPv4/IPv6 address. */ > static int > -netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h) > +netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h, > + vrf_id_t vrf_id) > { > int len; > struct ifaddrmsg *ifa; > @@ -556,19 +550,19 @@ netlink_interface_addr (struct sockaddr_nl *snl, > struct nlmsghdr *h) > memset (tb, 0, sizeof tb); > netlink_parse_rtattr (tb, IFA_MAX, IFA_RTA (ifa), len); > > - ifp = if_lookup_by_index (ifa->ifa_index); > + ifp = if_lookup_by_index_vrf (ifa->ifa_index, vrf_id); > if (ifp == NULL) > { > - zlog_err ("netlink_interface_addr can't find interface by index %d", > - ifa->ifa_index); > + zlog_err ("netlink_interface_addr can't find interface by index %d > vrf %u", > + ifa->ifa_index, vrf_id); > return -1; > } > > if (IS_ZEBRA_DEBUG_KERNEL) /* remove this line to see initial ifcfg > */ > { > char buf[BUFSIZ]; > - zlog_debug ("netlink_interface_addr %s %s:", > - lookup (nlmsg_str, h->nlmsg_type), ifp->name); > + zlog_debug ("netlink_interface_addr %s %s vrf %u:", > + lookup (nlmsg_str, h->nlmsg_type), ifp->name, vrf_id); > if (tb[IFA_LOCAL]) > zlog_debug (" IFA_LOCAL %s/%d", > inet_ntop (ifa->ifa_family, RTA_DATA (tb[IFA_LOCAL]), > @@ -661,7 +655,8 @@ netlink_interface_addr (struct sockaddr_nl *snl, > struct nlmsghdr *h) > > /* Looking up routing table by netlink interface. */ > static int > -netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h) > +netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h, > + vrf_id_t vrf_id) > { > int len; > struct rtmsg *rtm; > @@ -744,7 +739,7 @@ netlink_routing_table (struct sockaddr_nl *snl, struct > nlmsghdr *h) > > if (!tb[RTA_MULTIPATH]) > rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, src, index, > - VRF_DEFAULT, table, metric, 0, SAFI_UNICAST); > + vrf_id, table, metric, 0, SAFI_UNICAST); > else > { > /* This is a multipath route */ > @@ -760,7 +755,7 @@ netlink_routing_table (struct sockaddr_nl *snl, struct > nlmsghdr *h) > rib->distance = 0; > rib->flags = flags; > rib->metric = metric; > - rib->vrf_id = VRF_DEFAULT; > + rib->vrf_id = vrf_id; > rib->table = table; > rib->nexthop_num = 0; > rib->uptime = time (NULL); > @@ -810,7 +805,7 @@ netlink_routing_table (struct sockaddr_nl *snl, struct > nlmsghdr *h) > memcpy (&p.prefix, dest, 16); > p.prefixlen = rtm->rtm_dst_len; > > - rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, index, > VRF_DEFAULT, > + rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, index, vrf_id, > table, metric, 0, SAFI_UNICAST); > } > #endif /* HAVE_IPV6 */ > @@ -835,7 +830,8 @@ static const struct message rtproto_str[] = { > > /* Routing information change from the kernel. */ > static int > -netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h) > +netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h, > + vrf_id_t vrf_id) > { > int len; > struct rtmsg *rtm; > @@ -856,18 +852,19 @@ netlink_route_change (struct sockaddr_nl *snl, > struct nlmsghdr *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\n", h->nlmsg_type); > + zlog_warn ("Kernel message: %d vrf %u\n", h->nlmsg_type, vrf_id); > return 0; > } > > /* Connected route. */ > if (IS_ZEBRA_DEBUG_KERNEL) > - zlog_debug ("%s %s %s proto %s", > + zlog_debug ("%s %s %s proto %s vrf %u", > h->nlmsg_type == > RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE", > rtm->rtm_family == AF_INET ? "ipv4" : "ipv6", > rtm->rtm_type == RTN_UNICAST ? "unicast" : "multicast", > - lookup (rtproto_str, rtm->rtm_protocol)); > + lookup (rtproto_str, rtm->rtm_protocol), > + vrf_id); > > if (rtm->rtm_type != RTN_UNICAST) > { > @@ -899,7 +896,7 @@ netlink_route_change (struct sockaddr_nl *snl, struct > nlmsghdr *h) > > if (rtm->rtm_src_len != 0) > { > - zlog_warn ("netlink_route_change(): no src len"); > + zlog_warn ("netlink_route_change(): no src len, vrf %u", vrf_id); > return 0; > } > > @@ -936,15 +933,15 @@ netlink_route_change (struct sockaddr_nl *snl, > struct nlmsghdr *h) > if (IS_ZEBRA_DEBUG_KERNEL) > { > char buf[PREFIX_STRLEN]; > - zlog_debug ("%s %s", > + zlog_debug ("%s %s vrf %u", > h->nlmsg_type == RTM_NEWROUTE ? "RTM_NEWROUTE" : > "RTM_DELROUTE", > - prefix2str (&p, buf, sizeof(buf))); > + prefix2str (&p, buf, sizeof(buf)), vrf_id); > } > > if (h->nlmsg_type == RTM_NEWROUTE) > { > if (!tb[RTA_MULTIPATH]) > - rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, src, index, > VRF_DEFAULT, > + rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, src, index, > vrf_id, > table, metric, 0, SAFI_UNICAST); > else > { > @@ -961,7 +958,7 @@ netlink_route_change (struct sockaddr_nl *snl, struct > nlmsghdr *h) > rib->distance = 0; > rib->flags = 0; > rib->metric = metric; > - rib->vrf_id = VRF_DEFAULT; > + rib->vrf_id = vrf_id; > rib->table = table; > rib->nexthop_num = 0; > rib->uptime = time (NULL); > @@ -1004,7 +1001,7 @@ netlink_route_change (struct sockaddr_nl *snl, > struct nlmsghdr *h) > } > } > else > - rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, > VRF_DEFAULT, > + rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, vrf_id, > SAFI_UNICAST); > } > > @@ -1020,16 +1017,16 @@ netlink_route_change (struct sockaddr_nl *snl, > struct nlmsghdr *h) > if (IS_ZEBRA_DEBUG_KERNEL) > { > char buf[PREFIX_STRLEN]; > - zlog_debug ("%s %s", > + zlog_debug ("%s %s vrf %u", > h->nlmsg_type == RTM_NEWROUTE ? "RTM_NEWROUTE" : > "RTM_DELROUTE", > - prefix2str (&p, buf, sizeof(buf))); > + prefix2str (&p, buf, sizeof(buf)), vrf_id); > } > > if (h->nlmsg_type == RTM_NEWROUTE) > - rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, > VRF_DEFAULT, table, > + rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, vrf_id, > table, > metric, 0, SAFI_UNICAST); > else > - rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, > VRF_DEFAULT, > + rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, vrf_id, > SAFI_UNICAST); > } > #endif /* HAVE_IPV6 */ > @@ -1038,7 +1035,8 @@ netlink_route_change (struct sockaddr_nl *snl, > struct nlmsghdr *h) > } > > static int > -netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h) > +netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h, > + vrf_id_t vrf_id) > { > int len; > struct ifinfomsg *ifi; > @@ -1051,8 +1049,8 @@ netlink_link_change (struct sockaddr_nl *snl, struct > nlmsghdr *h) > if (!(h->nlmsg_type == RTM_NEWLINK || h->nlmsg_type == RTM_DELLINK)) > { > /* If this is not link add/delete message so print warning. */ > - zlog_warn ("netlink_link_change: wrong kernel message %d\n", > - h->nlmsg_type); > + zlog_warn ("netlink_link_change: wrong kernel message %d vrf %u\n", > + h->nlmsg_type, vrf_id); > return 0; > } > > @@ -1069,7 +1067,8 @@ netlink_link_change (struct sockaddr_nl *snl, struct > nlmsghdr *h) > if ((tb[IFLA_WIRELESS] != NULL) && (ifi->ifi_change == 0)) > { > if (IS_ZEBRA_DEBUG_KERNEL) > - zlog_debug ("%s: ignoring IFLA_WIRELESS message", __func__); > + zlog_debug ("%s: ignoring IFLA_WIRELESS message, vrf %u", > __func__, > + vrf_id); > return 0; > } > #endif /* IFLA_WIRELESS */ > @@ -1081,12 +1080,12 @@ netlink_link_change (struct sockaddr_nl *snl, > struct nlmsghdr *h) > /* Add interface. */ > if (h->nlmsg_type == RTM_NEWLINK) > { > - ifp = if_lookup_by_name (name); > + ifp = if_lookup_by_name_vrf (name, vrf_id); > > if (ifp == NULL || !CHECK_FLAG (ifp->status, > ZEBRA_INTERFACE_ACTIVE)) > { > if (ifp == NULL) > - ifp = if_get_by_name (name); > + ifp = if_get_by_name_vrf (name, vrf_id); > > set_ifindex(ifp, ifi->ifi_index); > ifp->flags = ifi->ifi_flags & 0x0000fffff; > @@ -1127,12 +1126,12 @@ netlink_link_change (struct sockaddr_nl *snl, > struct nlmsghdr *h) > else > { > /* RTM_DELLINK. */ > - ifp = if_lookup_by_name (name); > + ifp = if_lookup_by_name_vrf (name, vrf_id); > > if (ifp == NULL) > { > - zlog (NULL, LOG_WARNING, "interface %s is deleted but can't > find", > - name); > + zlog_warn ("interface %s vrf %u is deleted but can't find", > + name, vrf_id); > return 0; > } > > @@ -1143,7 +1142,8 @@ netlink_link_change (struct sockaddr_nl *snl, struct > nlmsghdr *h) > } > > static int > -netlink_information_fetch (struct sockaddr_nl *snl, struct nlmsghdr *h) > +netlink_information_fetch (struct sockaddr_nl *snl, struct nlmsghdr *h, > + vrf_id_t vrf_id) > { > /* JF: Ignore messages that aren't from the kernel */ > if ( snl->nl_pid != 0 ) > @@ -1155,25 +1155,26 @@ netlink_information_fetch (struct sockaddr_nl > *snl, struct nlmsghdr *h) > switch (h->nlmsg_type) > { > case RTM_NEWROUTE: > - return netlink_route_change (snl, h); > + return netlink_route_change (snl, h, vrf_id); > break; > case RTM_DELROUTE: > - return netlink_route_change (snl, h); > + return netlink_route_change (snl, h, vrf_id); > break; > case RTM_NEWLINK: > - return netlink_link_change (snl, h); > + return netlink_link_change (snl, h, vrf_id); > break; > case RTM_DELLINK: > - return netlink_link_change (snl, h); > + return netlink_link_change (snl, h, vrf_id); > break; > case RTM_NEWADDR: > - return netlink_interface_addr (snl, h); > + return netlink_interface_addr (snl, h, vrf_id); > break; > case RTM_DELADDR: > - return netlink_interface_addr (snl, h); > + return netlink_interface_addr (snl, h, vrf_id); > break; > default: > - zlog_warn ("Unknown netlink nlmsg_type %d\n", h->nlmsg_type); > + zlog_warn ("Unknown netlink nlmsg_type %d vrf %u\n", h->nlmsg_type, > + vrf_id); > break; > } > return 0; > @@ -1181,32 +1182,32 @@ netlink_information_fetch (struct sockaddr_nl > *snl, struct nlmsghdr *h) > > /* Interface lookup by netlink socket. */ > int > -interface_lookup_netlink (void) > +interface_lookup_netlink (struct zebra_vrf *zvrf) > { > int ret; > > /* Get interface information. */ > - ret = netlink_request (AF_PACKET, RTM_GETLINK, &netlink_cmd); > + ret = netlink_request (AF_PACKET, RTM_GETLINK, &zvrf->netlink_cmd); > if (ret < 0) > return ret; > - ret = netlink_parse_info (netlink_interface, &netlink_cmd); > + ret = netlink_parse_info (netlink_interface, &zvrf->netlink_cmd, zvrf); > if (ret < 0) > return ret; > > /* Get IPv4 address of the interfaces. */ > - ret = netlink_request (AF_INET, RTM_GETADDR, &netlink_cmd); > + ret = netlink_request (AF_INET, RTM_GETADDR, &zvrf->netlink_cmd); > if (ret < 0) > return ret; > - ret = netlink_parse_info (netlink_interface_addr, &netlink_cmd); > + ret = netlink_parse_info (netlink_interface_addr, &zvrf->netlink_cmd, > zvrf); > if (ret < 0) > return ret; > > #ifdef HAVE_IPV6 > /* Get IPv6 address of the interfaces. */ > - ret = netlink_request (AF_INET6, RTM_GETADDR, &netlink_cmd); > + ret = netlink_request (AF_INET6, RTM_GETADDR, &zvrf->netlink_cmd); > if (ret < 0) > return ret; > - ret = netlink_parse_info (netlink_interface_addr, &netlink_cmd); > + ret = netlink_parse_info (netlink_interface_addr, &zvrf->netlink_cmd, > zvrf); > if (ret < 0) > return ret; > #endif /* HAVE_IPV6 */ > @@ -1217,24 +1218,24 @@ interface_lookup_netlink (void) > /* Routing table read function using netlink interface. Only called > bootstrap time. */ > int > -netlink_route_read (void) > +netlink_route_read (struct zebra_vrf *zvrf) > { > int ret; > > /* Get IPv4 routing table. */ > - ret = netlink_request (AF_INET, RTM_GETROUTE, &netlink_cmd); > + ret = netlink_request (AF_INET, RTM_GETROUTE, &zvrf->netlink_cmd); > if (ret < 0) > return ret; > - ret = netlink_parse_info (netlink_routing_table, &netlink_cmd); > + ret = netlink_parse_info (netlink_routing_table, &zvrf->netlink_cmd, > zvrf); > if (ret < 0) > return ret; > > #ifdef HAVE_IPV6 > /* Get IPv6 routing table. */ > - ret = netlink_request (AF_INET6, RTM_GETROUTE, &netlink_cmd); > + ret = netlink_request (AF_INET6, RTM_GETROUTE, &zvrf->netlink_cmd); > if (ret < 0) > return ret; > - ret = netlink_parse_info (netlink_routing_table, &netlink_cmd); > + ret = netlink_parse_info (netlink_routing_table, &zvrf->netlink_cmd, > zvrf); > if (ret < 0) > return ret; > #endif /* HAVE_IPV6 */ > @@ -1307,15 +1308,17 @@ addattr32 (struct nlmsghdr *n, size_t maxlen, int > type, int data) > } > > static int > -netlink_talk_filter (struct sockaddr_nl *snl, struct nlmsghdr *h) > +netlink_talk_filter (struct sockaddr_nl *snl, struct nlmsghdr *h, > + vrf_id_t vrf_id) > { > - zlog_warn ("netlink_talk: ignoring message type 0x%04x", h->nlmsg_type); > + zlog_warn ("netlink_talk: ignoring message type 0x%04x vrf %u", > h->nlmsg_type, > + vrf_id); > return 0; > } > > /* sendmsg() to netlink socket then recvmsg(). */ > static int > -netlink_talk (struct nlmsghdr *n, struct nlsock *nl) > +netlink_talk (struct nlmsghdr *n, struct nlsock *nl, struct zebra_vrf > *zvrf) > { > int status; > struct sockaddr_nl snl; > @@ -1364,7 +1367,7 @@ netlink_talk (struct nlmsghdr *n, struct nlsock *nl) > * Get reply from netlink socket. > * The reply should either be an acknowlegement or an error. > */ > - return netlink_parse_info (netlink_talk_filter, nl); > + return netlink_parse_info (netlink_talk_filter, nl, zvrf); > } > > /* This function takes a nexthop as argument and adds > @@ -1558,12 +1561,13 @@ _netlink_route_debug( > struct prefix *p, > struct nexthop *nexthop, > const char *routedesc, > - int family) > + int family, > + struct zebra_vrf *zvrf) > { > if (IS_ZEBRA_DEBUG_KERNEL) > { > char buf[PREFIX_STRLEN]; > - zlog_debug ("netlink_route_multipath() (%s): %s %s type %s", > + zlog_debug ("netlink_route_multipath() (%s): %s %s vrf %u type %s", > routedesc, > lookup (nlmsg_str, cmd), > prefix2str (p, buf, sizeof(buf)), > @@ -1591,6 +1595,8 @@ netlink_route_multipath (int cmd, struct prefix *p, > struct rib *rib, > char buf[NL_PKT_BUF_SIZE]; > } req; > > + struct zebra_vrf *zvrf = vrf_info_lookup (rib->vrf_id); > + > memset (&req, 0, sizeof req - NL_PKT_BUF_SIZE); > > bytelen = (family == AF_INET ? 4 : 16); > @@ -1675,7 +1681,7 @@ netlink_route_multipath (int cmd, struct prefix *p, > struct rib *rib, > { > routedesc = recursing ? "recursive, 1 hop" : "single hop"; > > - _netlink_route_debug(cmd, p, nexthop, routedesc, family); > + _netlink_route_debug(cmd, p, nexthop, routedesc, family, > zvrf); > _netlink_route_build_singlepath(routedesc, bytelen, > nexthop, &req.n, &req.r, > sizeof req); > @@ -1717,7 +1723,7 @@ netlink_route_multipath (int cmd, struct prefix *p, > struct rib *rib, > nexthop_num++; > > _netlink_route_debug(cmd, p, nexthop, > - routedesc, family); > + routedesc, family, zvrf); > _netlink_route_build_multipath(routedesc, bytelen, > nexthop, rta, rtnh, &src); > rtnh = RTNH_NEXT (rtnh); > @@ -1749,7 +1755,7 @@ skip: > snl.nl_family = AF_NETLINK; > > /* Talk to netlink socket. */ > - return netlink_talk (&req.n, &netlink_cmd); > + return netlink_talk (&req.n, &zvrf->netlink_cmd, zvrf); > } > > int > @@ -1793,6 +1799,8 @@ netlink_address (int cmd, int family, struct > interface *ifp, > char buf[NL_PKT_BUF_SIZE]; > } req; > > + struct zebra_vrf *zvrf = vrf_info_lookup (ifp->vrf_id); > + > p = ifc->address; > memset (&req, 0, sizeof req - NL_PKT_BUF_SIZE); > > @@ -1825,7 +1833,7 @@ netlink_address (int cmd, int family, struct > interface *ifp, > addattr_l (&req.n, sizeof req, IFA_LABEL, ifc->label, > strlen (ifc->label) + 1); > > - return netlink_talk (&req.n, &netlink_cmd); > + return netlink_talk (&req.n, &zvrf->netlink_cmd, zvrf); > } > > int > @@ -1847,8 +1855,10 @@ extern struct thread_master *master; > static int > kernel_read (struct thread *thread) > { > - netlink_parse_info (netlink_information_fetch, &netlink); > - thread_add_read (zebrad.master, kernel_read, NULL, netlink.sock); > + struct zebra_vrf *zvrf = (struct zebra_vrf *)THREAD_ARG (thread); > + netlink_parse_info (netlink_information_fetch, &zvrf->netlink, zvrf); > + zvrf->t_netlink = thread_add_read (zebrad.master, kernel_read, zvrf, > + zvrf->netlink.sock); > > return 0; > } > @@ -1887,7 +1897,7 @@ static void netlink_install_filter (int sock, __u32 > pid) > /* Exported interface function. This function simply calls > netlink_socket (). */ > void > -kernel_init (void) > +kernel_init (struct zebra_vrf *zvrf) > { > unsigned long groups; > > @@ -1895,23 +1905,42 @@ kernel_init (void) > #ifdef HAVE_IPV6 > groups |= RTMGRP_IPV6_ROUTE | RTMGRP_IPV6_IFADDR; > #endif /* HAVE_IPV6 */ > - netlink_socket (&netlink, groups); > - netlink_socket (&netlink_cmd, 0); > + netlink_socket (&zvrf->netlink, groups, zvrf->vrf_id); > + netlink_socket (&zvrf->netlink_cmd, 0, zvrf->vrf_id); > > /* Register kernel socket. */ > - if (netlink.sock > 0) > + if (zvrf->netlink.sock > 0) > { > /* Only want non-blocking on the netlink event socket */ > - if (fcntl (netlink.sock, F_SETFL, O_NONBLOCK) < 0) > - zlog (NULL, LOG_ERR, "Can't set %s socket flags: %s", netlink.name > , > - safe_strerror (errno)); > + if (fcntl (zvrf->netlink.sock, F_SETFL, O_NONBLOCK) < 0) > + zlog_err ("Can't set %s socket flags: %s", zvrf->netlink.name, > + safe_strerror (errno)); > > /* Set receive buffer size if it's set from command line */ > if (nl_rcvbufsize) > - netlink_recvbuf (&netlink, nl_rcvbufsize); > + netlink_recvbuf (&zvrf->netlink, nl_rcvbufsize); > > - netlink_install_filter (netlink.sock, netlink_cmd.snl.nl_pid); > - thread_add_read (zebrad.master, kernel_read, NULL, netlink.sock); > + netlink_install_filter (zvrf->netlink.sock, > zvrf->netlink_cmd.snl.nl_pid); > + zvrf->t_netlink = thread_add_read (zebrad.master, kernel_read, zvrf, > + zvrf->netlink.sock); > + } > +} > + > +void > +kernel_terminate (struct zebra_vrf *zvrf) > +{ > + THREAD_READ_OFF (zvrf->t_netlink); > + > + if (zvrf->netlink.sock >= 0) > + { > + close (zvrf->netlink.sock); > + zvrf->netlink.sock = -1; > + } > + > + if (zvrf->netlink_cmd.sock >= 0) > + { > + close (zvrf->netlink_cmd.sock); > + zvrf->netlink_cmd.sock = -1; > } > } > > diff --git a/zebra/rt_netlink.h b/zebra/rt_netlink.h > index d8f9db8561fe..40fa8eb4b8ce 100644 > --- a/zebra/rt_netlink.h > +++ b/zebra/rt_netlink.h > @@ -41,8 +41,8 @@ extern const char * > nl_rtproto_to_str (u_char rtproto); > > > -extern int interface_lookup_netlink (void); > -extern int netlink_route_read (void); > +extern int interface_lookup_netlink (struct zebra_vrf *zvrf); > +extern int netlink_route_read (struct zebra_vrf *zvrf); > > #endif /* HAVE_NETLINK */ > > diff --git a/zebra/rtread_getmsg.c b/zebra/rtread_getmsg.c > index 83ef64832388..7fb916ffa52a 100644 > --- a/zebra/rtread_getmsg.c > +++ b/zebra/rtread_getmsg.c > @@ -96,7 +96,7 @@ handle_route_entry (mib2_ipRouteEntry_t *routeEntry) > } > > void > -route_read (void) > +route_read (struct zebra_vrf *zvrf) > { > char storage[RT_BUFSIZ]; > > @@ -111,6 +111,10 @@ route_read (void) > struct strbuf msgdata; > int flags, dev, retval, process; > > + if (zvrf->vrf_id != VRF_DEFAULT) { > + return; > + } > + > if ((dev = open (_PATH_GETMSG_ROUTE, O_RDWR)) == -1) { > zlog_warn ("can't open %s: %s", _PATH_GETMSG_ROUTE, > safe_strerror (errno)); > diff --git a/zebra/rtread_netlink.c b/zebra/rtread_netlink.c > index 7abbc590a4df..1f658646e0ac 100644 > --- a/zebra/rtread_netlink.c > +++ b/zebra/rtread_netlink.c > @@ -25,7 +25,7 @@ > #include "zebra/zserv.h" > #include "rt_netlink.h" > > -void route_read (void) > +void route_read (struct zebra_vrf *zvrf) > { > - netlink_route_read (); > + netlink_route_read (zvrf); > } > diff --git a/zebra/rtread_sysctl.c b/zebra/rtread_sysctl.c > index b8f5bde70e3d..385e15069fae 100644 > --- a/zebra/rtread_sysctl.c > +++ b/zebra/rtread_sysctl.c > @@ -24,6 +24,7 @@ > > #include "memory.h" > #include "log.h" > +#include "vrf.h" > > #include "zebra/zserv.h" > #include "zebra/rt.h" > @@ -31,7 +32,7 @@ > > /* Kernel routing table read up by sysctl function. */ > void > -route_read (void) > +route_read (struct zebra_vrf *zvrf) > { > caddr_t buf, end, ref; > size_t bufsiz; > @@ -47,7 +48,10 @@ route_read (void) > NET_RT_DUMP, > 0 > }; > - > + > + if (zvrf->vrf_id != VRF_DEFAULT) > + return; > + > /* Get buffer size. */ > if (sysctl (mib, MIBSIZ, NULL, &bufsiz, NULL, 0) < 0) > { > diff --git a/zebra/test_main.c b/zebra/test_main.c > index 17014ea7312b..448d1ef9f1ac 100644 > --- a/zebra/test_main.c > +++ b/zebra/test_main.c > @@ -220,6 +220,9 @@ zebra_vrf_enable (vrf_id_t vrf_id, void **info) > > assert (zvrf); > > + kernel_init (zvrf); > + route_read (zvrf); > + > return 0; > } > > @@ -244,6 +247,8 @@ zebra_vrf_disable (vrf_id_t vrf_id, void **info) > if_down (ifp); > } > > + kernel_terminate (zvrf); > + > return 0; > } > > @@ -355,8 +360,6 @@ main (int argc, char **argv) > > /* Make kernel routing socket. */ > zebra_vrf_init (); > - kernel_init (); > - route_read (); > zebra_vty_init(); > > /* Configuration file read*/ > diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c > index 9d966a0f2f9c..084af3802323 100644 > --- a/zebra/zebra_rib.c > +++ b/zebra/zebra_rib.c > @@ -3447,6 +3447,9 @@ struct zebra_vrf * > zebra_vrf_alloc (vrf_id_t vrf_id) > { > struct zebra_vrf *zvrf; > +#ifdef HAVE_NETLINK > + char nl_name[64]; > +#endif > > zvrf = XCALLOC (MTYPE_ZEBRA_VRF, sizeof (struct zebra_vrf)); > > @@ -3463,6 +3466,17 @@ zebra_vrf_alloc (vrf_id_t vrf_id) > /* Set VRF ID */ > zvrf->vrf_id = vrf_id; > > +#ifdef HAVE_NETLINK > + /* Initialize netlink sockets */ > + snprintf (nl_name, 64, "netlink-listen (vrf %u)", vrf_id); > + zvrf->netlink.sock = -1; > + zvrf->netlink.name = XSTRDUP (MTYPE_NETLINK_NAME, nl_name); > + > + snprintf (nl_name, 64, "netlink-cmd (vrf %u)", vrf_id); > + zvrf->netlink_cmd.sock = -1; > + zvrf->netlink_cmd.name = XSTRDUP (MTYPE_NETLINK_NAME, nl_name); > +#endif > + > return zvrf; > } > > diff --git a/zebra/zserv.h b/zebra/zserv.h > index eaa164b956f2..af005f851d2a 100644 > --- a/zebra/zserv.h > +++ b/zebra/zserv.h > @@ -92,9 +92,10 @@ extern void zebra_if_init (void); > extern void zebra_zserv_socket_init (char *path); > extern void hostinfo_get (void); > extern void rib_init (void); > -extern void interface_list (void); > -extern void kernel_init (void); > -extern void route_read (void); > +extern void interface_list (struct zebra_vrf *); > +extern void route_read (struct zebra_vrf *); > +extern void kernel_init (struct zebra_vrf *); > +extern void kernel_terminate (struct zebra_vrf *); > extern void zebra_route_map_init (void); > extern void zebra_snmp_init (void); > extern void zebra_vty_init (void); > -- > 2.4.2 > >
_______________________________________________ Quagga-dev mailing list Quagga-dev@lists.quagga.net https://lists.quagga.net/mailman/listinfo/quagga-dev