]> git.puffer.fish Git - matthieu/frr.git/commitdiff
zebra, lib/memtypes.c: the netlink sockets work per VRF
authorFeng Lu <lu.feng@6wind.com>
Thu, 3 Jul 2014 10:23:09 +0000 (18:23 +0800)
committerVipin Kumar <vipin@cumulusnetworks.com>
Fri, 30 Oct 2015 08:45:21 +0000 (01:45 -0700)
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.feng@6wind.com>
Reviewed-by: Alain Ritoux <alain.ritoux@6wind.com>
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Acked-by: Donald Sharp <sharpd@cumulusnetworks.com>
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

17 files changed:
lib/memtypes.c
zebra/if_ioctl.c
zebra/if_ioctl_solaris.c
zebra/if_netlink.c
zebra/if_sysctl.c
zebra/kernel_null.c
zebra/kernel_socket.c
zebra/main.c
zebra/rib.h
zebra/rt_netlink.c
zebra/rt_netlink.h
zebra/rtread_getmsg.c
zebra/rtread_netlink.c
zebra/rtread_sysctl.c
zebra/test_main.c
zebra/zebra_rib.c
zebra/zserv.h

index dafd471dd280260c4f3352965d031444641273cb..fc50443600bb93c00c900828286e0ccb6cd78aca 100644 (file)
@@ -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 },
 };
 
index f357e15447c363ad3be6922654fb77952690542d..8df877dbaaa11226e008ee0f532d813c983a8c1e 100644 (file)
 #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
index fc384ea29a3f4a0c966bd8494cec8b3ce2d43bac..3f33f749af461ef1be18c8c40c3771d07029c18c 100644 (file)
 #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);
index 2016986cb5c52e2a5407bffa51a513db193009d0..9562f2f586ce8d621ffd3d343c1074d952d22b93 100644 (file)
@@ -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);
 }
index 1150ec1b068ad6fcb3ae51b49b94be3ebfc23cea..e7b25d1f8f8ec55b022964a94cec6aa881630b6a 100644 (file)
 #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) 
     {
index 5f37e0cc7c030f5e440af962b8804c7c138860ea..08fef9b309a9ae01ba55b7f86de97db636a58291 100644 (file)
@@ -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
index a1002a4d865c9ae2c58706e432cac35bb827a616..7b4f70fa83fedf2c17e53ec0d8a3bfde72a8adf4 100644 (file)
@@ -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;
 }
index 16a11edea3eff90f43d4aa374322d1a87e262590..4b2a89856ed5755cb705c7f9f0cf6d9b68fa17d9 100644 (file)
@@ -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 ();
index f18b311d47b6a3078176cdce0b003711594fef8d..25ab68df131110564a9c363b719f405a9efe4efa 100644 (file)
@@ -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
    */
index e312801e5593bc93a1a7cce54ca7a6655536b1da..cad367808db30ab947c919ee4347481aa92f97fb 100644 (file)
 
 #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;
     }
 }
 
index 5b1b48cb0a79071990c1b6be91fad220637a4c9b..d45d22f936ccc8946bbd7c08e1c4f005548b4e84 100644 (file)
@@ -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 */
 
index f9bfb338a08850995a3902839ea47a82db0b625b..6975390415f3dbad8dea99a30f1578b628ec0772 100644 (file)
@@ -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));
index 09191d517bec8764e54206041b4a20753d0507a3..5b264497989bed55bc4f40b9b1b6cc3b6f879423 100644 (file)
@@ -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);
 }
index 69d45950ae7261770f3ad514b155687fa220af93..2a9601a304cbfded1d3af451ad816c9b74baecf7 100644 (file)
@@ -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) 
     {
index 9b83b642d4be15dc0e0e1b31f0ca116293f5b466..027d2a158005c89097838d7b9f2322203cba9365 100644 (file)
@@ -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*/
index ee7abc432ca53f80aa9e19ba20fbde33bff76354..5fd6545ffed5a286334af60e40f326c2181ccbb1 100644 (file)
@@ -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;
 }
 
index 29b3145672ca352dbf42c1dbf1c8e0258cb6bc61..f4da43d0b0189cb7ca6cef76346dff2deb3e6ae5 100644 (file)
@@ -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);