From 78104b9bad14a3185178cedc0dd41d1b1c5db493 Mon Sep 17 00:00:00 2001 From: Feng Lu Date: Fri, 22 May 2015 11:40:02 +0200 Subject: zebra: let FIB stand for its respective VRF A new member "vrf_id" is added to "struct rib", reflecting the VRF which it belongs to. A new parameter "vrf_id" is added to the relative functions where need, except those: - which already have the parameter "vrf_id"; or - which have a parameter in type of "struct rib"; or - which have a parameter in type of "struct interface". All incoming routes are set to default VRF. In fact, all routes in FIB are kept in default VRF. And the logic is not changed. Signed-off-by: Feng Lu Reviewed-by: Alain Ritoux Signed-off-by: Nicolas Dichtel Acked-by: Vincent JARDIN [DL: conflicts fixed + compile warning fix] Signed-off-by: David Lamparter Conflicts: zebra/connected.c zebra/kernel_socket.c zebra/rib.h zebra/rt_netlink.c zebra/zebra_rib.c zebra/zserv.c Conflicts: zebra/connected.c zebra/interface.c zebra/kernel_socket.c zebra/rib.h zebra/rt_netlink.c zebra/rtread_getmsg.c zebra/zebra_rib.c zebra/zebra_vty.c zebra/zserv.c --- zebra/rtread_getmsg.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'zebra/rtread_getmsg.c') diff --git a/zebra/rtread_getmsg.c b/zebra/rtread_getmsg.c index 17d75b283a..f9bfb338a0 100644 --- a/zebra/rtread_getmsg.c +++ b/zebra/rtread_getmsg.c @@ -25,6 +25,7 @@ #include "prefix.h" #include "log.h" #include "if.h" +#include "vrf.h" #include "zebra/rib.h" #include "zebra/zserv.h" @@ -90,7 +91,7 @@ handle_route_entry (mib2_ipRouteEntry_t *routeEntry) gateway.s_addr = routeEntry->ipRouteNextHop; rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &prefix, - &gateway, NULL, 0, 0, 0, 0, SAFI_UNICAST); + &gateway, NULL, 0, VRF_DEFAULT, 0, 0, 0, SAFI_UNICAST); } void -- cgit v1.2.3 From 8f7d9fc0883869bb32f67b4f70f017141d412ccb Mon Sep 17 00:00:00 2001 From: Feng Lu Date: Thu, 3 Jul 2014 18:23:09 +0800 Subject: zebra, lib/memtypes.c: the netlink sockets work per VRF 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 Reviewed-by: Alain Ritoux Signed-off-by: Nicolas Dichtel Acked-by: Donald Sharp Conflicts: lib/memtypes.c zebra/rib.h zebra/rt_netlink.c Conflicts: zebra/if_netlink.c zebra/if_sysctl.c zebra/kernel_null.c zebra/rib.h zebra/rt_netlink.c zebra/rt_netlink.h --- lib/memtypes.c | 1 + zebra/if_ioctl.c | 9 +- zebra/if_ioctl_solaris.c | 9 +- zebra/if_netlink.c | 4 +- zebra/if_sysctl.c | 14 ++- zebra/kernel_null.c | 6 +- zebra/kernel_socket.c | 16 +++- zebra/main.c | 8 +- zebra/rib.h | 17 ++++ zebra/rt_netlink.c | 244 ++++++++++++++++++++++++++--------------------- 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, 244 insertions(+), 134 deletions(-) (limited to 'zebra/rtread_getmsg.c') diff --git a/lib/memtypes.c b/lib/memtypes.c index dafd471dd2..fc50443600 100644 --- a/lib/memtypes.c +++ b/lib/memtypes.c @@ -90,6 +90,7 @@ struct memory_list memory_list_zebra[] = { MTYPE_RIB_DEST, "RIB destination" }, { MTYPE_RIB_TABLE_INFO, "RIB table info" }, { MTYPE_RNH, "Nexthop tracking object" }, + { MTYPE_NETLINK_NAME, "Netlink name" }, { -1, NULL }, }; diff --git a/zebra/if_ioctl.c b/zebra/if_ioctl.c index f357e15447..8df877dbaa 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 fc384ea29a..3f33f749af 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 2016986cb5..9562f2f586 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 1150ec1b06..e7b25d1f8f 100644 --- a/zebra/if_sysctl.c +++ b/zebra/if_sysctl.c @@ -29,9 +29,15 @@ #include "memory.h" #include "ioctl.h" #include "log.h" +<<<<<<< HEAD +======= +#include "interface.h" +#include "vrf.h" +>>>>>>> 3c27b5f... zebra, lib/memtypes.c: the netlink sockets work per VRF #include "zebra/rt.h" #include "zebra/kernel_socket.h" +#include "zebra/rib.h" void ifstat_update_sysctl (void) @@ -90,7 +96,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 +113,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 5f37e0cc7c..08fef9b309 100644 --- a/zebra/kernel_null.c +++ b/zebra/kernel_null.c @@ -8,6 +8,7 @@ #include "zebra/redistribute.h" #include "zebra/connected.h" #include "zebra/rt_netlink.h" +#include "zebra/rib.h" int kernel_add_ipv4 (struct prefix *a, struct rib *b) { return 0; } int kernel_update_ipv4 (struct prefix *a, struct rib *b) { return 0; } @@ -54,9 +55,10 @@ int netlink_neigh_update (int cmd, int ifindex, __u32 addr, char *lla, int llale 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 a1002a4d86..7b4f70fa83 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; @@ -1262,8 +1263,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"); @@ -1294,7 +1298,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 16a11edea3..4b2a89856e 100644 --- a/zebra/main.c +++ b/zebra/main.c @@ -241,6 +241,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; } @@ -268,6 +272,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); @@ -428,9 +433,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 f18b311d47..25ab68df13 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -310,6 +310,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 { @@ -340,6 +351,12 @@ struct zebra_vrf /* Routing tables off of main table for redistribute table */ struct route_table *other_table[AFI_MAX][ZEBRA_KERNEL_TABLE_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 e312801e55..cad367808d 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -47,16 +47,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"}, @@ -156,7 +146,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; @@ -170,7 +160,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))) @@ -376,7 +367,7 @@ netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *), return 0; } - if (nl == &netlink_cmd + if (nl == &zvrf->netlink_cmd && msg_type == RTM_NEWROUTE && -errnum == ESRCH) { /* This is known to happen in some situations, don't log @@ -407,16 +398,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); @@ -487,7 +479,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; @@ -523,7 +516,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]); @@ -540,7 +533,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; @@ -570,19 +564,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]), @@ -675,7 +669,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; @@ -756,7 +751,7 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h) if (!tb[RTA_MULTIPATH]) rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, 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 */ @@ -772,7 +767,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); @@ -823,7 +818,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, 0, flags, &p, gate, index, VRF_DEFAULT, + rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, flags, &p, gate, index, vrf_id, table, metric, 0, SAFI_UNICAST); } #endif /* HAVE_IPV6 */ @@ -848,7 +843,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; @@ -870,18 +866,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) { @@ -913,7 +910,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; } @@ -949,18 +946,16 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h) if (IS_ZEBRA_DEBUG_KERNEL) { - if (h->nlmsg_type == RTM_NEWROUTE) - zlog_debug ("RTM_NEWROUTE %s/%d", - inet_ntoa (p.prefix), p.prefixlen); - else - zlog_debug ("RTM_DELROUTE %s/%d", - inet_ntoa (p.prefix), p.prefixlen); + char buf[BUFSIZ]; + zlog_debug ("%s %s vrf %u", + h->nlmsg_type == RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE", + prefix2str (&p, buf, sizeof(buf)), vrf_id); } if (h->nlmsg_type == RTM_NEWROUTE) { if (!tb[RTA_MULTIPATH]) - rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, 0, &p, gate, src, index, VRF_DEFAULT, + rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, 0, &p, gate, src, index, vrf_id, table, metric, 0, SAFI_UNICAST); else { @@ -977,7 +972,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); @@ -1023,7 +1018,7 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h) } else rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, gate, index, - VRF_DEFAULT, table, SAFI_UNICAST); + vrf_id, table, SAFI_UNICAST); } #ifdef HAVE_IPV6 @@ -1038,22 +1033,17 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h) if (IS_ZEBRA_DEBUG_KERNEL) { - if (h->nlmsg_type == RTM_NEWROUTE) - zlog_debug ("RTM_NEWROUTE %s/%d", - inet_ntop (AF_INET6, &p.prefix, buf, BUFSIZ), - p.prefixlen); - else - zlog_debug ("RTM_DELROUTE %s/%d", - inet_ntop (AF_INET6, &p.prefix, buf, BUFSIZ), - p.prefixlen); + zlog_debug ("%s %s vrf %u", + h->nlmsg_type == RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE", + prefix2str (&p, buf, sizeof(buf)), vrf_id); } if (h->nlmsg_type == RTM_NEWROUTE) - rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, 0, &p, gate, index, VRF_DEFAULT, + rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, 0, &p, gate, index, vrf_id, table, metric, 0, SAFI_UNICAST); else rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, gate, index, - VRF_DEFAULT, table, SAFI_UNICAST); + vrf_id, table, SAFI_UNICAST); } #endif /* HAVE_IPV6 */ @@ -1061,7 +1051,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; @@ -1074,8 +1065,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; } @@ -1092,7 +1083,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 */ @@ -1104,12 +1096,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; @@ -1150,12 +1142,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; } @@ -1166,7 +1158,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 ) @@ -1178,25 +1171,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; @@ -1204,32 +1198,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 */ @@ -1240,24 +1234,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 */ @@ -1330,15 +1324,17 @@ addattr32 (struct nlmsghdr *n, unsigned int 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; @@ -1388,7 +1384,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); } /* Routing table change via netlink interface. */ @@ -1401,6 +1397,8 @@ netlink_route (int cmd, int family, void *dest, int length, void *gate, struct sockaddr_nl snl; int discard; + struct zebra_vrf *zvrf = vrf_info_lookup (VRF_DEFAULT); //Pending + struct { struct nlmsghdr n; @@ -1462,7 +1460,7 @@ netlink_route (int cmd, int family, void *dest, int length, void *gate, snl.nl_family = AF_NETLINK; /* Talk to netlink socket. */ - ret = netlink_talk (&req.n, &netlink_cmd); + ret = netlink_talk (&req.n, &zvrf->netlink_cmd, VRF_DEFAULT); if (ret < 0) return -1; @@ -1763,11 +1761,12 @@ _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) { - zlog_debug ("netlink_route_multipath() (%s): %s %s/%d type %s", + zlog_debug ("netlink_route_multipath() (%s): %s %s/%d vrf %u type %s", routedesc, lookup (nlmsg_str, cmd), #ifdef HAVE_IPV6 @@ -1776,7 +1775,7 @@ _netlink_route_debug( #else inet_ntoa (p->u.prefix4), #endif /* HAVE_IPV6 */ - p->prefixlen, nexthop_type_to_str (nexthop->type)); + p->prefixlen, zvrf->vrf_id, nexthop_type_to_str (nexthop->type)); } } @@ -1789,6 +1788,8 @@ netlink_neigh_update (int cmd, int ifindex, __u32 addr, char *lla, int llalen) char buf[256]; } req; + struct zebra_vrf *zvrf = vrf_info_lookup (VRF_DEFAULT); //Pending + memset(&req.n, 0, sizeof(req.n)); memset(&req.ndm, 0, sizeof(req.ndm)); @@ -1803,7 +1804,7 @@ netlink_neigh_update (int cmd, int ifindex, __u32 addr, char *lla, int llalen) addattr_l(&req.n, sizeof(req), NDA_DST, &addr, 4); addattr_l(&req.n, sizeof(req), NDA_LLADDR, lla, llalen); - return netlink_talk (&req.n, &netlink_cmd); + return netlink_talk (&req.n, &zvrf->netlink_cmd, VRF_DEFAULT); } /* Routing table change via netlink interface. */ @@ -1829,6 +1830,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); @@ -1950,7 +1953,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, cmd); @@ -2031,7 +2034,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, &req.r, &src1); rtnh = RTNH_NEXT (rtnh); @@ -2079,7 +2082,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 @@ -2142,6 +2145,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); @@ -2174,7 +2179,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 @@ -2196,8 +2201,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; } @@ -2236,7 +2243,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; @@ -2244,23 +2251,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 5b1b48cb0a..d45d22f936 100644 --- a/zebra/rt_netlink.h +++ b/zebra/rt_netlink.h @@ -44,8 +44,8 @@ nl_rtproto_to_str (u_char rtproto); int netlink_neigh_update (int cmd, int ifindex, __u32 addr, char *lla, int llalen); -extern int netlink_route_read(void); -extern int interface_lookup_netlink(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 f9bfb338a0..6975390415 100644 --- a/zebra/rtread_getmsg.c +++ b/zebra/rtread_getmsg.c @@ -95,7 +95,7 @@ handle_route_entry (mib2_ipRouteEntry_t *routeEntry) } void -route_read (void) +route_read (struct zebra_vrf *zvrf) { char storage[RT_BUFSIZ]; @@ -110,6 +110,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 09191d517b..5b26449798 100644 --- a/zebra/rtread_netlink.c +++ b/zebra/rtread_netlink.c @@ -25,7 +25,7 @@ #include "zebra/zserv.h" #include "zebra/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 69d45950ae..2a9601a304 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 9b83b642d4..027d2a1580 100644 --- a/zebra/test_main.c +++ b/zebra/test_main.c @@ -225,6 +225,9 @@ zebra_vrf_enable (vrf_id_t vrf_id, void **info) assert (zvrf); + kernel_init (zvrf); + route_read (zvrf); + return 0; } @@ -249,6 +252,8 @@ zebra_vrf_disable (vrf_id_t vrf_id, void **info) if_down (ifp); } + kernel_terminate (zvrf); + return 0; } @@ -363,8 +368,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 ee7abc432c..5fd6545ffe 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -4135,6 +4135,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)); @@ -4157,6 +4160,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 29b3145672..f4da43d0b0 100644 --- a/zebra/zserv.h +++ b/zebra/zserv.h @@ -134,9 +134,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); -- cgit v1.2.3