diff options
author | Donald Sharp <sharpd@cumulusnetworks.com> | 2016-02-01 19:55:42 +0100 |
---|---|---|
committer | Donald Sharp <sharpd@cumulusnetworks.com> | 2016-02-01 19:55:42 +0100 |
commit | 12f6fb97311c58742f305ef240f918aa5d57fa79 (patch) | |
tree | 47ba71dd454d8c1d7a110845f5a2743428d20d26 /zebra | |
parent | zebra: Add the 'struct zebra_ns' data structure (diff) | |
download | frr-12f6fb97311c58742f305ef240f918aa5d57fa79.tar.xz frr-12f6fb97311c58742f305ef240f918aa5d57fa79.zip |
lib, zebra: The Bulk of the conversion over to NS and VRF
Convert the rest of zebra over to use a Namespae and VRF.
Signed-off-by: Vipin Kumar <vipin@cumulusnetworks.com>
Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
Diffstat (limited to 'zebra')
-rw-r--r-- | zebra/if_ioctl.c | 10 | ||||
-rw-r--r-- | zebra/if_ioctl_solaris.c | 6 | ||||
-rw-r--r-- | zebra/if_netlink.c | 4 | ||||
-rw-r--r-- | zebra/if_sysctl.c | 6 | ||||
-rw-r--r-- | zebra/interface.c | 174 | ||||
-rw-r--r-- | zebra/interface.h | 8 | ||||
-rw-r--r-- | zebra/ioctl.c | 2 | ||||
-rw-r--r-- | zebra/kernel_null.c | 6 | ||||
-rw-r--r-- | zebra/kernel_socket.c | 11 | ||||
-rw-r--r-- | zebra/main.c | 57 | ||||
-rw-r--r-- | zebra/redistribute.c | 41 | ||||
-rw-r--r-- | zebra/redistribute.h | 4 | ||||
-rw-r--r-- | zebra/redistribute_null.c | 5 | ||||
-rw-r--r-- | zebra/rib.h | 21 | ||||
-rw-r--r-- | zebra/router-id.c | 4 | ||||
-rw-r--r-- | zebra/rt_netlink.c | 329 | ||||
-rw-r--r-- | zebra/rt_netlink.h | 4 | ||||
-rw-r--r-- | zebra/rtread_getmsg.c | 6 | ||||
-rw-r--r-- | zebra/rtread_netlink.c | 4 | ||||
-rw-r--r-- | zebra/rtread_sysctl.c | 4 | ||||
-rw-r--r-- | zebra/test_main.c | 7 | ||||
-rw-r--r-- | zebra/zebra_ptm_redistribute.c | 2 | ||||
-rw-r--r-- | zebra/zebra_rib.c | 87 | ||||
-rw-r--r-- | zebra/zebra_vty.c | 111 | ||||
-rw-r--r-- | zebra/zserv.c | 118 | ||||
-rw-r--r-- | zebra/zserv.h | 13 |
26 files changed, 825 insertions, 219 deletions
diff --git a/zebra/if_ioctl.c b/zebra/if_ioctl.c index 8df877dba..88fea3427 100644 --- a/zebra/if_ioctl.c +++ b/zebra/if_ioctl.c @@ -444,13 +444,11 @@ interface_info_ioctl () /* Lookup all interface information. */ void -interface_list (struct zebra_vrf *zvrf) +interface_list (struct zebra_ns *zns) { - if (zvrf->vrf_id != VRF_DEFAULT) - { - zlog_warn ("interface_list: ignore VRF %u", zvrf->vrf_id); - return; - } + + zlog_info ("interface_list: NS %u", zns->ns_id); + /* 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 3f33f749a..79137ccd3 100644 --- a/zebra/if_ioctl_solaris.c +++ b/zebra/if_ioctl_solaris.c @@ -351,11 +351,11 @@ interface_info_ioctl (struct interface *ifp) /* Lookup all interface information. */ void -interface_list (struct zebra_vrf *zvrf) +interface_list (struct zebra_ns *zns) { - if (zvrf->vrf_id != VRF_DEFAULT) + if (zns->ns_id != NS_DEFAULT) { - zlog_warn ("interface_list: ignore VRF %u", zvrf->vrf_id); + zlog_warn ("interface_list: ignore NS %u", zns->ns_id); return; } interface_list_ioctl (AF_INET); diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index 9562f2f58..dffa6568e 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -27,7 +27,7 @@ /* Interface information read by netlink. */ void -interface_list (struct zebra_vrf *zvrf) +interface_list (struct zebra_ns *zns) { - interface_lookup_netlink (zvrf); + interface_lookup_netlink (zns); } diff --git a/zebra/if_sysctl.c b/zebra/if_sysctl.c index 3e23954dc..d2a506e32 100644 --- a/zebra/if_sysctl.c +++ b/zebra/if_sysctl.c @@ -93,7 +93,7 @@ ifstat_update_sysctl (void) /* Interface listing up function using sysctl(). */ void -interface_list (struct zebra_vrf *zvrf) +interface_list (struct zebra_ns *zns) { caddr_t ref, buf, end; size_t bufsiz; @@ -110,9 +110,9 @@ interface_list (struct zebra_vrf *zvrf) 0 }; - if (zvrf->vrf_id != VRF_DEFAULT) + if (zns->ns_id != NS_DEFAULT) { - zlog_warn ("interface_list: ignore VRF %u", zvrf->vrf_id); + zlog_warn ("interface_list: ignore NS %u", zns->ns_id); return; } diff --git a/zebra/interface.c b/zebra/interface.c index cb4645c2f..be85ec4ac 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -54,6 +54,8 @@ const char *rtadv_pref_strs[] = { "medium", "high", "INVALID", "low", 0 }; #endif /* HAVE_RTADV */ +struct zebra_ns *dzns; + /* Called when new interface is added. */ static int if_zebra_new_hook (struct interface *ifp) @@ -121,6 +123,67 @@ if_zebra_delete_hook (struct interface *ifp) return 0; } +/* Build the table key */ +static void +if_build_key (u_int32_t ifindex, struct prefix *p) +{ + p->family = AF_INET; + p->prefixlen = IPV4_MAX_BITLEN; + p->u.prefix4.s_addr = ifindex; +} + +/* Link an interface in a per NS interface tree */ +struct interface * +if_link_per_ns (struct zebra_ns *ns, struct interface *ifp) +{ + struct prefix p; + struct route_node *rn; + + if (ifp->ifindex == IFINDEX_INTERNAL) + return NULL; + + if_build_key (ifp->ifindex, &p); + rn = route_node_get (ns->if_table, &p); + if (rn->info) + { + ifp = (struct interface *)rn->info; + route_unlock_node (rn); /* get */ + return ifp; + } + + rn->info = ifp; + ifp->node = rn; + + return ifp; +} + +/* Delete a VRF. This is called in vrf_terminate(). */ +void +if_unlink_per_ns (struct interface *ifp) +{ + ifp->node->info = NULL; + route_unlock_node(ifp->node); +} + +/* Look up an interface by identifier within a NS */ +struct interface * +if_lookup_by_index_per_ns (struct zebra_ns *ns, u_int32_t ifindex) +{ + struct prefix p; + struct route_node *rn; + struct interface *ifp = NULL; + + if_build_key (ifindex, &p); + rn = route_node_lookup (ns->if_table, &p); + if (rn) + { + ifp = (struct interface *)rn->info; + route_unlock_node (rn); /* lookup */ + } + return ifp; +} + + /* Tie an interface address to its derived subnet list of addresses. */ int if_subnet_add (struct interface *ifp, struct connected *ifc) @@ -374,6 +437,8 @@ if_add_update (struct interface *ifp) { struct zebra_if *if_data; + if_link_per_ns(dzns, ifp); + if_data = ifp->info; if (if_data->multicast == IF_ZEBRA_MULTICAST_ON) if_set_flags (ifp, IFF_MULTICAST); @@ -525,6 +590,8 @@ if_delete_update (struct interface *ifp) } zebra_interface_delete_update (ifp); + if_unlink_per_ns(ifp); + /* Update ifindex after distributing the delete message. This is in case any client needs to have the old value of ifindex available while processing the deletion. Each client daemon is responsible @@ -533,6 +600,52 @@ if_delete_update (struct interface *ifp) ifp->ifindex = IFINDEX_INTERNAL; } +/* Handle VRF addition */ +void +vrf_add_update (struct vrf *vrfp) +{ + zebra_vrf_add_update (vrfp); + + if (! CHECK_FLAG (vrfp->status, ZEBRA_VRF_ACTIVE)) + { + SET_FLAG (vrfp->status, ZEBRA_VRF_ACTIVE); + + //Pending: Check if the equivalent of if_addr_wakeup (ifp) is needed here. + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug ("VRF %s id %u becomes active.", + vrfp->name, vrfp->vrf_id); + } + else + { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug ("VRF %s id %u is added.", + vrfp->name, vrfp->vrf_id); + } +} + +/* Handle an interface delete event */ +void +vrf_delete_update (struct vrf *vrfp) +{ + /* Mark VRF as inactive */ + UNSET_FLAG (vrfp->status, ZEBRA_VRF_ACTIVE); + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug ("VRF %s id %u is now inactive.", + vrfp->name, vrfp->vrf_id); + + zebra_vrf_delete_update (vrfp); + + /* Pending: Update ifindex after distributing the delete message. This is in + case any client needs to have the old value of ifindex available + while processing the deletion. Each client daemon is responsible + for setting vrf-id to IFINDEX_INTERNAL after processing the + interface deletion message. */ + vrfp->vrf_id = 0; +} + + static void ipv6_ll_address_to_mac (struct in6_addr *address, u_char *mac) { @@ -1043,6 +1156,34 @@ struct cmd_node interface_node = 1 }; +/* Wrapper hook point for zebra daemon so that ifindex can be set + * DEFUN macro not used as extract.pl HAS to ignore this + * See also interface_cmd in lib/if.c + */ +DEFUN_NOSH (zebra_vrf, + zebra_vrf_cmd, + "vrf NAME", + "Select a VRF to configure\n" + "VRF's name\n") +{ + int ret; + + /* Call lib vrf() */ + if ((ret = vrf_cmd.func (self, vty, argc, argv)) != CMD_SUCCESS) + return ret; + + // vrfp = vty->index; + + return ret; +} + +struct cmd_node vrf_node = +{ + VRF_NODE, + "%s(config-vrf)# ", + 1 +}; + /* Show all interfaces to vty. */ DEFUN (show_interface, show_interface_cmd, "show interface", @@ -1063,7 +1204,7 @@ DEFUN (show_interface, show_interface_cmd, #endif /* HAVE_NET_RT_IFLIST */ if (argc > 0) - VTY_GET_INTEGER ("VRF ID", vrf_id, argv[0]); + VRF_GET_ID (vrf_id, argv[0]); /* All interface print. */ for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp)) @@ -1127,7 +1268,7 @@ DEFUN (show_interface_name, show_interface_name_cmd, #endif /* HAVE_NET_RT_IFLIST */ if (argc > 1) - VTY_GET_INTEGER ("VRF ID", vrf_id, argv[1]); + VRF_GET_ID (vrf_id, argv[1]); /* Specified interface print. */ ifp = if_lookup_by_name_vrf (argv[0], vrf_id); @@ -1242,7 +1383,7 @@ DEFUN (show_interface_desc, vrf_id_t vrf_id = VRF_DEFAULT; if (argc > 0) - VTY_GET_INTEGER ("VRF ID", vrf_id, argv[0]); + VRF_GET_ID (vrf_id, argv[0]); if_show_description (vty, vrf_id); @@ -1874,13 +2015,15 @@ if_config_write (struct vty *vty) struct listnode *addrnode; struct connected *ifc; struct prefix *p; + struct vrf *vrf; if_data = ifp->info; + vrf = vrf_lookup(ifp->vrf_id); if (ifp->vrf_id == VRF_DEFAULT) vty_out (vty, "interface %s%s", ifp->name, VTY_NEWLINE); else - vty_out (vty, "interface %s vrf %u%s", ifp->name, ifp->vrf_id, + vty_out (vty, "interface %s vrf %s%s", ifp->name, vrf->name, VTY_NEWLINE); if (if_data) @@ -1940,6 +2083,23 @@ if_config_write (struct vty *vty) return 0; } +static int +vrf_config_write (struct vty *vty) +{ + struct listnode *node; + struct vrf *vrf; + + for (ALL_LIST_ELEMENTS_RO (vrf_list, node, vrf)) + { + if (strcmp(vrf->name, VRF_DEFAULT_NAME)) + { + vty_out (vty, "vrf %s%s", vrf->name, VTY_NEWLINE); + vty_out (vty, "!%s", VTY_NEWLINE); + } + } + return 0; +} + /* Allocate and initialize interface vector. */ void zebra_if_init (void) @@ -1950,6 +2110,7 @@ zebra_if_init (void) /* Install configuration write function. */ install_node (&interface_node, if_config_write); + install_node (&vrf_node, vrf_config_write); install_element (VIEW_NODE, &show_interface_cmd); install_element (VIEW_NODE, &show_interface_vrf_cmd); @@ -1992,4 +2153,9 @@ zebra_if_init (void) install_element (INTERFACE_NODE, &ip_address_label_cmd); install_element (INTERFACE_NODE, &no_ip_address_label_cmd); #endif /* HAVE_NETLINK */ + + install_element (CONFIG_NODE, &zebra_vrf_cmd); + install_element (CONFIG_NODE, &no_vrf_cmd); + install_default (VRF_NODE); + } diff --git a/zebra/interface.h b/zebra/interface.h index 6f253a467..ab018596c 100644 --- a/zebra/interface.h +++ b/zebra/interface.h @@ -23,6 +23,7 @@ #define _ZEBRA_INTERFACE_H #include "redistribute.h" +#include "vrf.h" #ifdef HAVE_IRDP #include "zebra/irdp.h" @@ -206,6 +207,10 @@ struct zebra_if #endif /* SUNOS_5 */ }; + +extern struct interface *if_lookup_by_index_per_ns (struct zebra_ns *, u_int32_t); +extern struct interface *if_link_per_ns (struct zebra_ns *, struct interface *); +extern void if_unlink_per_ns (struct interface *); extern void if_nbr_ipv6ll_to_ipv4ll_neigh_update (struct interface *ifp, struct in6_addr *address, int add); extern void if_nbr_ipv6ll_to_ipv4ll_neigh_del_all (struct interface *ifp); @@ -219,6 +224,9 @@ extern int if_subnet_add (struct interface *, struct connected *); extern int if_subnet_delete (struct interface *, struct connected *); extern int ipv6_address_configured (struct interface *ifp); +extern void vrf_delete_update (struct vrf *vrfp); +extern void vrf_add_update (struct vrf *vrfp); + #ifdef HAVE_PROC_NET_DEV extern void ifstat_update_proc (void); #endif /* HAVE_PROC_NET_DEV */ diff --git a/zebra/ioctl.c b/zebra/ioctl.c index d783b0a38..24df98557 100644 --- a/zebra/ioctl.c +++ b/zebra/ioctl.c @@ -196,7 +196,7 @@ if_set_prefix (struct interface *ifp, struct connected *ifc) struct prefix_ipv4 *p; p = (struct prefix_ipv4 *) ifc->address; - rib_lookup_and_pushup (p); + rib_lookup_and_pushup (p, ifp->vrf_id); memset (&addreq, 0, sizeof addreq); strncpy ((char *)&addreq.ifra_name, ifp->name, sizeof addreq.ifra_name); diff --git a/zebra/kernel_null.c b/zebra/kernel_null.c index 64d854a06..b69ffcab6 100644 --- a/zebra/kernel_null.c +++ b/zebra/kernel_null.c @@ -56,10 +56,10 @@ int netlink_neigh_update (int cmd, int ifindex, __u32 addr, char *lla, int llale return 0; } -void kernel_init (struct zebra_vrf *zvrf) { return; } -void kernel_terminate (struct zebra_vrf *zvrf) { return; } +void kernel_init (struct zebra_ns *zns) { return; } +void kernel_terminate (struct zebra_ns *zns) { return; } #ifdef HAVE_SYS_WEAK_ALIAS_PRAGMA #pragma weak route_read = kernel_init #else -void route_read (struct zebra_vrf *zvrf) { return; } +void route_read (struct zebra_ns *zns) { return; } #endif diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c index a7179ff4b..028109cb2 100644 --- a/zebra/kernel_socket.c +++ b/zebra/kernel_socket.c @@ -1263,11 +1263,8 @@ kernel_read (struct thread *thread) /* Make routing socket. */ static void -routing_socket (struct zebra_vrf *zvrf) +routing_socket (struct zebra_ns *zns) { - if (zvrf->vrf_id != VRF_DEFAULT) - return; - if ( zserv_privs.change (ZPRIVS_RAISE) ) zlog_err ("routing_socket: Can't raise privileges"); @@ -1298,13 +1295,13 @@ routing_socket (struct zebra_vrf *zvrf) /* Exported interface function. This function simply calls routing_socket (). */ void -kernel_init (struct zebra_vrf *zvrf) +kernel_init (struct zebra_ns *zns) { - routing_socket (zvrf); + routing_socket (zns); } void -kernel_terminate (struct zebra_vrf *zvrf) +kernel_terminate (struct zebra_ns *zns) { return; } diff --git a/zebra/main.c b/zebra/main.c index d65877a2c..ad7a020e6 100644 --- a/zebra/main.c +++ b/zebra/main.c @@ -213,16 +213,18 @@ struct quagga_signal_t zebra_signals[] = .handler = &sigint, }, }; - + /* Callback upon creating a new VRF. */ static int zebra_vrf_new (vrf_id_t vrf_id, const char *name, void **info) { struct zebra_vrf *zvrf = *info; + zlog_info ("ZVRF %s with id %u", name, vrf_id); + if (! zvrf) { - zvrf = zebra_vrf_alloc (vrf_id); + zvrf = zebra_vrf_alloc (vrf_id, name); *info = (void *)zvrf; router_id_init (zvrf); } @@ -230,6 +232,32 @@ zebra_vrf_new (vrf_id_t vrf_id, const char *name, void **info) return 0; } +static int +zebra_ns_enable (ns_id_t ns_id, void **info) +{ + struct zebra_ns *zns = (struct zebra_ns *) (*info); +#ifdef HAVE_NETLINK + char nl_name[64]; +#endif + +#ifdef HAVE_NETLINK + /* Initialize netlink sockets */ + snprintf (nl_name, 64, "netlink-listen (NS %u)", ns_id); + zns->netlink.sock = -1; + zns->netlink.name = XSTRDUP (MTYPE_NETLINK_NAME, nl_name); + + snprintf (nl_name, 64, "netlink-cmd (NS %u)", ns_id); + zns->netlink_cmd.sock = -1; + zns->netlink_cmd.name = XSTRDUP (MTYPE_NETLINK_NAME, nl_name); +#endif + zns->if_table = route_table_init (); + kernel_init (zns); + interface_list (zns); + route_read (zns); + + return 0; +} + /* Callback upon enabling a VRF. */ static int zebra_vrf_enable (vrf_id_t vrf_id, const char *name, void **info) @@ -241,13 +269,22 @@ zebra_vrf_enable (vrf_id_t vrf_id, const char *name, void **info) #if defined (HAVE_RTADV) rtadv_init (zvrf); #endif - kernel_init (zvrf); - interface_list (zvrf); - route_read (zvrf); return 0; } +/* +static int +zebra_ns_disable (ns_id_t ns_id, void **info) +{ + struct zebra_ns *zns = (struct zebra_ns *) (*info); + + kernel_terminate (zns); + + return 0; +} +*/ + /* Callback upon disabling a VRF. */ static int zebra_vrf_disable (vrf_id_t vrf_id, const char *name, void **info) @@ -272,7 +309,6 @@ zebra_vrf_disable (vrf_id_t vrf_id, const char *name, void **info) #if defined (HAVE_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); @@ -284,10 +320,19 @@ zebra_vrf_disable (vrf_id_t vrf_id, const char *name, void **info) static void zebra_vrf_init (void) { + struct zebra_ns *zns; + vrf_add_hook (VRF_NEW_HOOK, zebra_vrf_new); vrf_add_hook (VRF_ENABLE_HOOK, zebra_vrf_enable); vrf_add_hook (VRF_DISABLE_HOOK, zebra_vrf_disable); + + /* Default NS initialization */ + + zns = XCALLOC (MTYPE_ZEBRA_VRF, sizeof (struct zebra_ns)); + dzns = zns; //Pending: Doing it all for the default namespace only for now. + vrf_init (); + zebra_ns_enable (0, (void **)&zns); } /* Main startup routine. */ diff --git a/zebra/redistribute.c b/zebra/redistribute.c index 8cd3dddd4..552524dbc 100644 --- a/zebra/redistribute.c +++ b/zebra/redistribute.c @@ -456,6 +456,47 @@ zebra_interface_delete_update (struct interface *ifp) } } +/* VRF information update. */ +void +zebra_vrf_add_update (struct vrf *vrfp) +{ + struct listnode *node, *nnode; + struct zserv *client; + + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug ("MESSAGE: ZEBRA_VRF_ADD %s", vrfp->name); + + for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) + zsend_vrf_add (client, vrfp); +} + +void +zebra_vrf_delete_update (struct vrf *vrfp) +{ + struct listnode *node, *nnode; + struct zserv *client; + + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug ("MESSAGE: ZEBRA_VRF_DELETE %s", vrfp->name); + + for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) + zsend_vrf_delete (client, vrfp); +} + +void +zebra_vrf_update_all (struct zserv *client) +{ + struct vrf *vrf; + vrf_iter_t iter; + + for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + { + if ((vrf = vrf_iter2vrf (iter)) && vrf->vrf_id) + zsend_vrf_add (client, vrf); + } +} + + /* Interface address addition. */ void zebra_interface_address_add_update (struct interface *ifp, diff --git a/zebra/redistribute.h b/zebra/redistribute.h index 833aa0e5d..d56e3d0b9 100644 --- a/zebra/redistribute.h +++ b/zebra/redistribute.h @@ -26,6 +26,7 @@ #include "table.h" #include "zserv.h" #include "vty.h" +#include "vrf.h" extern void zebra_redistribute_add (int, struct zserv *, int, vrf_id_t); extern void zebra_redistribute_delete (int, struct zserv *, int, vrf_id_t); @@ -41,6 +42,9 @@ extern void redistribute_delete (struct prefix *, struct rib *); extern void zebra_interface_up_update (struct interface *); extern void zebra_interface_down_update (struct interface *); +extern void zebra_vrf_add_update (struct vrf *); +extern void zebra_vrf_update_all (struct zserv *); +extern void zebra_vrf_delete_update (struct vrf *); extern void zebra_interface_add_update (struct interface *); extern void zebra_interface_delete_update (struct interface *); diff --git a/zebra/redistribute_null.c b/zebra/redistribute_null.c index c491c2baa..44295be98 100644 --- a/zebra/redistribute_null.c +++ b/zebra/redistribute_null.c @@ -47,6 +47,11 @@ void zebra_interface_delete_update (struct interface *a) { return; } #endif +void zebra_vrf_add_update (struct vrf *a) +{ return; } +void zebra_vrf_delete_update (struct vrf *a) +{ return; } + void zebra_interface_address_add_update (struct interface *a, struct connected *b) { return; } diff --git a/zebra/rib.h b/zebra/rib.h index ba0aa4b72..df0e993f7 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -295,10 +295,15 @@ struct zebra_ns /* Identifier. */ ns_id_t ns_id; +#ifdef HAVE_NETLINK + struct nlsock netlink; /* kernel messages */ + struct nlsock netlink_cmd; /* command channel */ + struct thread *t_netlink; +#endif + struct route_table *if_table; }; - /* Routing table instance. */ struct zebra_vrf { @@ -331,12 +336,6 @@ 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 */ @@ -356,6 +355,8 @@ struct zebra_vrf struct zebra_ns *zns; }; +extern struct zebra_ns *dzns; + /* * rib_table_info_t * @@ -413,8 +414,8 @@ extern void rib_nexthop_add (struct rib *rib, struct nexthop *nexthop); extern void rib_copy_nexthops (struct rib *rib, struct nexthop *nh); extern int nexthop_has_fib_child(struct nexthop *); -extern void rib_lookup_and_dump (struct prefix_ipv4 *); -extern void rib_lookup_and_pushup (struct prefix_ipv4 *); +extern void rib_lookup_and_dump (struct prefix_ipv4 *, vrf_id_t); +extern void rib_lookup_and_pushup (struct prefix_ipv4 *, vrf_id_t); #define rib_dump(prefix ,rib) _rib_dump(__func__, prefix, rib) extern void _rib_dump (const char *, union prefix46constptr, const struct rib *); @@ -432,7 +433,7 @@ extern struct nexthop *rib_nexthop_ipv6_ifindex_add (struct rib *rib, unsigned int ifindex); extern struct zebra_vrf *zebra_vrf_lookup (vrf_id_t vrf_id); -extern struct zebra_vrf *zebra_vrf_alloc (vrf_id_t); +extern struct zebra_vrf *zebra_vrf_alloc (vrf_id_t, const char *); extern struct route_table *zebra_vrf_table (afi_t, safi_t, vrf_id_t); extern struct route_table *zebra_vrf_static_table (afi_t, safi_t, vrf_id_t); extern struct route_table *zebra_vrf_other_route_table (afi_t afi, u_int32_t table_id, diff --git a/zebra/router-id.c b/zebra/router-id.c index 82f5a105f..3277dd178 100644 --- a/zebra/router-id.c +++ b/zebra/router-id.c @@ -230,7 +230,7 @@ DEFUN (router_id, rid.family = AF_INET; if (argc > 1) - VTY_GET_INTEGER ("VRF ID", vrf_id, argv[1]); + VRF_GET_ID (vrf_id, argv[1]); router_id_set (&rid, vrf_id); @@ -258,7 +258,7 @@ DEFUN (no_router_id, rid.family = AF_INET; if (argc > 1) - VTY_GET_INTEGER ("VRF ID", vrf_id, argv[1]); + VRF_GET_ID (vrf_id, argv[1]); router_id_set (&rid, vrf_id); diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index b49dcc175..2921a11ff 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -44,6 +44,7 @@ #include "zebra/redistribute.h" #include "zebra/interface.h" #include "zebra/debug.h" +#include "zebra/rtadv.h" #include "rt_netlink.h" @@ -73,7 +74,7 @@ set_ifindex(struct interface *ifp, unsigned int ifi_index) { struct interface *oifp; - if (((oifp = if_lookup_by_index(ifi_index)) != NULL) && (oifp != ifp)) + if (((oifp = if_lookup_by_index_per_ns (dzns, ifi_index)) != NULL) && (oifp != ifp)) { if (ifi_index == IFINDEX_INTERNAL) zlog_err("Netlink is setting interface %s ifindex to reserved " @@ -146,7 +147,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, vrf_id_t vrf_id) +netlink_socket (struct nlsock *nl, unsigned long groups, ns_id_t ns_id) { int ret; struct sockaddr_nl snl; @@ -160,7 +161,7 @@ netlink_socket (struct nlsock *nl, unsigned long groups, vrf_id_t vrf_id) return -1; } - sock = vrf_socket (AF_NETLINK, SOCK_RAW, NETLINK_ROUTE, vrf_id); + sock = vrf_socket (AF_NETLINK, SOCK_RAW, NETLINK_ROUTE, ns_id); if (sock < 0) { zlog (NULL, LOG_ERR, "Can't open %s socket: %s", nl->name, @@ -260,12 +261,33 @@ netlink_request (int family, int type, struct nlsock *nl) return 0; } +/* +Pending: create an efficient table_id (in a tree/hash) based lookup) + */ +static vrf_id_t +vrf_lookup_by_table (u_int32_t table_id) +{ + struct zebra_vrf *zvrf; + vrf_iter_t iter; + + for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + { + if ((zvrf = vrf_iter2info (iter)) == NULL || + (zvrf->table_id != table_id)) + continue; + + return zvrf->vrf_id; + } + + return VRF_DEFAULT; +} + /* 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 *, - vrf_id_t), - struct nlsock *nl, struct zebra_vrf *zvrf) + ns_id_t), + struct nlsock *nl, struct zebra_ns *zns) { int status; int ret = 0; @@ -354,7 +376,7 @@ netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *, } /* Deal with errors that occur because of races in link handling */ - if (nl == &zvrf->netlink_cmd + if (nl == &zns->netlink_cmd && ((msg_type == RTM_DELROUTE && (-errnum == ENODEV || -errnum == ESRCH)) || (msg_type == RTM_NEWROUTE && -errnum == EEXIST))) @@ -367,7 +389,7 @@ netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *, return 0; } - if (nl == &zvrf->netlink_cmd + if (nl == &zns->netlink_cmd && msg_type == RTM_NEWROUTE && -errnum == ESRCH) { /* This is known to happen in some situations, don't log @@ -398,17 +420,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 != &zvrf->netlink_cmd - && h->nlmsg_pid == zvrf->netlink_cmd.snl.nl_pid + if (nl != &zns->netlink_cmd + && h->nlmsg_pid == zns->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", - zvrf->netlink_cmd.name, nl->name); + zns->netlink_cmd.name, nl->name); continue; } - error = (*filter) (&snl, h, zvrf->vrf_id); + error = (*filter) (&snl, h, zns->ns_id); if (error < 0) { zlog (NULL, LOG_ERR, "%s filter function error", nl->name); @@ -476,6 +498,98 @@ netlink_interface_update_hw_addr (struct rtattr **tb, struct interface *ifp) } } +#define parse_rtattr_nested(tb, max, rta) \ + netlink_parse_rtattr((tb), (max), RTA_DATA(rta), RTA_PAYLOAD(rta)) + +static void +netlink_vrf_change (struct nlmsghdr *h, struct rtattr *tb, const char *name) +{ + struct ifinfomsg *ifi; + struct rtattr *linkinfo[IFLA_INFO_MAX+1]; + struct rtattr *attr[IFLA_VRF_MAX+1]; + struct vrf *vrf; + struct zebra_vrf *zvrf; + u_int32_t nl_table_id; + + ifi = NLMSG_DATA (h); + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug ("%s: received VRF device message: %s", __func__, name); + + parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb); + + if (!linkinfo[IFLA_INFO_DATA]) { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug ("%s: IFLA_INFO_DATA missing from VRF message: %s", __func__, name); + return; + } + + parse_rtattr_nested(attr, IFLA_VRF_MAX, linkinfo[IFLA_INFO_DATA]); + if (!attr[IFLA_VRF_TABLE]) { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug ("%s: IFLA_VRF_TABLE missing from VRF message: %s", __func__, name); + return; + } + + nl_table_id = *(u_int32_t *)RTA_DATA(attr[IFLA_VRF_TABLE]); + + if (h->nlmsg_type == RTM_NEWLINK) + { + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug ("%s: RTM_NEWLINK for VRF index %u, table %u", __func__, + ifi->ifi_index, nl_table_id); + + vrf = vrf_get((vrf_id_t)ifi->ifi_index, name); // It would create vrf + if (!vrf) + { + zlog_err ("VRF %s id %u not created", name, ifi->ifi_index); + return; + } + + /* Enable the created VRF. */ + if (!vrf_enable (vrf)) + { + zlog_err ("Failed to enable VRF %s id %u", name, ifi->ifi_index); + return; + } + + /*Pending: See if you want to optimize this code.. vrf, zvrf all have name */ + zvrf = vrf->info; + zvrf->table_id = nl_table_id; + + vrf_add_update(vrf); + } + else //h->nlmsg_type == RTM_DELLINK + { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug ("%s: RTM_DELLINK for vrf id %u", __func__, ifi->ifi_index); + + vrf = vrf_lookup ((vrf_id_t)ifi->ifi_index); + + if (!vrf) + zlog_warn ("%s: vrf not found", __func__); + + vrf_delete_update(vrf); + + //Pending: keeping VRF around just like its for other links. + //vrf_delete (vrf); + } +} + +static char * +parse_link_kind (struct rtattr *tb) +{ + struct rtattr *linkinfo[IFLA_INFO_MAX+1]; + + memset (linkinfo, 0, sizeof(struct rtattr *)*(IFLA_INFO_MAX+1)); + parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb); + + if (linkinfo[IFLA_INFO_KIND]) + return RTA_DATA(linkinfo[IFLA_INFO_KIND]); + + return NULL; +} /* Called from interface_lookup_netlink(). This function is only used during bootstrap. */ static int @@ -518,6 +632,20 @@ netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h, return -1; name = (char *) RTA_DATA (tb[IFLA_IFNAME]); + if (tb[IFLA_LINKINFO]) + { + char *kind = parse_link_kind(tb[IFLA_LINKINFO]); + + if (kind && strcmp(kind, "vrf") == 0) + { + netlink_vrf_change(h, tb[IFLA_LINKINFO], name); + return 0; + } + } + + if (tb[IFLA_MASTER]) + vrf_id = *(u_int32_t *)RTA_DATA(tb[IFLA_MASTER]); + /* Add interface. */ ifp = if_get_by_name_vrf (name, vrf_id); set_ifindex(ifp, ifi->ifi_index); @@ -537,7 +665,7 @@ 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, - vrf_id_t vrf_id) + ns_id_t ns_id) { int len; struct ifaddrmsg *ifa; @@ -548,6 +676,8 @@ netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h, u_char flags = 0; char *label = NULL; + vrf_id_t vrf_id = ns_id; + ifa = NLMSG_DATA (h); if (ifa->ifa_family != AF_INET @@ -567,7 +697,7 @@ 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_vrf (ifa->ifa_index, vrf_id); + ifp = if_lookup_by_index_per_ns (dzns, ifa->ifa_index); if (ifp == NULL) { zlog_err ("netlink_interface_addr can't find interface by index %d vrf %u", @@ -708,6 +838,8 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h, if (!is_zebra_valid_kernel_table(table) && !is_zebra_main_routing_table(table)) return 0; + vrf_id = vrf_lookup_by_table(table); + len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg)); if (len < 0) return -1; @@ -854,7 +986,7 @@ static const struct message rtproto_str[] = { /* Routing information change from the kernel. */ static int netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h, - vrf_id_t vrf_id) + ns_id_t ns_id) { int len; struct rtmsg *rtm; @@ -871,6 +1003,8 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h, void *gate; void *src; + vrf_id_t vrf_id = ns_id; + rtm = NLMSG_DATA (h); if (!(h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE)) @@ -899,6 +1033,8 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h, if (!is_zebra_valid_kernel_table(table) && !is_zebra_main_routing_table(table)) return 0; + vrf_id = vrf_lookup_by_table(table); + len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg)); if (len < 0) return -1; @@ -1062,13 +1198,17 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h, static int netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h, - vrf_id_t vrf_id) + ns_id_t ns_id) { int len; struct ifinfomsg *ifi; struct rtattr *tb[IFLA_MAX + 1]; struct interface *ifp; char *name; + struct connected *ifc; + struct listnode *node; + + vrf_id_t vrf_id = ns_id; ifi = NLMSG_DATA (h); @@ -1106,21 +1246,58 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h, return -1; name = (char *) RTA_DATA (tb[IFLA_IFNAME]); + if (tb[IFLA_LINKINFO]) + { + char *kind = parse_link_kind(tb[IFLA_LINKINFO]); + + if (kind && strcmp(kind, "vrf") == 0) + { + netlink_vrf_change(h, tb[IFLA_LINKINFO], name); + return 0; + } + } + /* Add interface. */ if (h->nlmsg_type == RTM_NEWLINK) { - ifp = if_lookup_by_name_vrf (name, vrf_id); + if (tb[IFLA_MASTER]) + vrf_id = *(u_int32_t *)RTA_DATA(tb[IFLA_MASTER]); - if (ifp == NULL || !CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE)) + /* clean up any old ifps in a different VRF */ + ifp = if_lookup_by_index_per_ns (dzns, ifi->ifi_index); + if (ifp && ifp->vrf_id != vrf_id) + { + if_down (ifp); //Ideally, we should have down/delete come from kernel + // if_delete_update (ifp); //Pending: see how best to make the old ifp unusable + for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, ifc)) + if (ifc->address->family == AF_INET6) + ipv6_nd_suppress_ra_set (ifp, RA_SUPPRESS); + } + + if (ifp == NULL || !CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE) || + ifp->vrf_id != vrf_id) { if (ifp == NULL) ifp = if_get_by_name_vrf (name, vrf_id); + else + { + if_update_vrf (ifp, name, strlen(name), vrf_id); + + for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, ifc)) + if (ifc->address->family == AF_INET6) + ipv6_nd_suppress_ra_set (ifp, RA_ENABLE); + } set_ifindex(ifp, ifi->ifi_index); ifp->flags = ifi->ifi_flags & 0x0000fffff; ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]); ifp->metric = 0; + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug ("%s: RTM_NEWLINK for %s vrf_id %u", __func__, name, + ifp->vrf_id); + + netlink_interface_update_hw_addr (tb, ifp); /* If new link is added. */ @@ -1133,6 +1310,12 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h, ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]); ifp->metric = 0; + // Pending, handle the vrf_id change.. + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug ("%s: RTM_NEWLINK status for %s vrf_id %u", __func__, name, + ifp->vrf_id); + netlink_interface_update_hw_addr (tb, ifp); if (if_is_no_ptm_operative (ifp)) @@ -1154,6 +1337,9 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h, } else { + if (tb[IFLA_MASTER]) + vrf_id = *(u_int32_t *)RTA_DATA(tb[IFLA_MASTER]); + /* RTM_DELLINK. */ ifp = if_lookup_by_name_vrf (name, vrf_id); @@ -1172,7 +1358,7 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h, static int netlink_information_fetch (struct sockaddr_nl *snl, struct nlmsghdr *h, - vrf_id_t vrf_id) + ns_id_t ns_id) { /* JF: Ignore messages that aren't from the kernel */ if ( snl->nl_pid != 0 ) @@ -1184,26 +1370,26 @@ netlink_information_fetch (struct sockaddr_nl *snl, struct nlmsghdr *h, switch (h->nlmsg_type) { case RTM_NEWROUTE: - return netlink_route_change (snl, h, vrf_id); + return netlink_route_change (snl, h, ns_id); break; case RTM_DELROUTE: - return netlink_route_change (snl, h, vrf_id); + return netlink_route_change (snl, h, ns_id); break; case RTM_NEWLINK: - return netlink_link_change (snl, h, vrf_id); + return netlink_link_change (snl, h, ns_id); break; case RTM_DELLINK: - return netlink_link_change (snl, h, vrf_id); + return netlink_link_change (snl, h, ns_id); break; case RTM_NEWADDR: - return netlink_interface_addr (snl, h, vrf_id); + return netlink_interface_addr (snl, h, ns_id); break; case RTM_DELADDR: - return netlink_interface_addr (snl, h, vrf_id); + return netlink_interface_addr (snl, h, ns_id); break; default: zlog_warn ("Unknown netlink nlmsg_type %d vrf %u\n", h->nlmsg_type, - vrf_id); + ns_id); break; } return 0; @@ -1211,32 +1397,32 @@ netlink_information_fetch (struct sockaddr_nl *snl, struct nlmsghdr *h, /* Interface lookup by netlink socket. */ int -interface_lookup_netlink (struct zebra_vrf *zvrf) +interface_lookup_netlink (struct zebra_ns *zns) { int ret; /* Get interface information. */ - ret = netlink_request (AF_PACKET, RTM_GETLINK, &zvrf->netlink_cmd); + ret = netlink_request (AF_PACKET, RTM_GETLINK, &zns->netlink_cmd); if (ret < 0) return ret; - ret = netlink_parse_info (netlink_interface, &zvrf->netlink_cmd, zvrf); + ret = netlink_parse_info (netlink_interface, &zns->netlink_cmd, zns); if (ret < 0) return ret; /* Get IPv4 address of the interfaces. */ - ret = netlink_request (AF_INET, RTM_GETADDR, &zvrf->netlink_cmd); + ret = netlink_request (AF_INET, RTM_GETADDR, &zns->netlink_cmd); if (ret < 0) return ret; - ret = netlink_parse_info (netlink_interface_addr, &zvrf->netlink_cmd, zvrf); + ret = netlink_parse_info (netlink_interface_addr, &zns->netlink_cmd, zns); if (ret < 0) return ret; #ifdef HAVE_IPV6 /* Get IPv6 address of the interfaces. */ - ret = netlink_request (AF_INET6, RTM_GETADDR, &zvrf->netlink_cmd); + ret = netlink_request (AF_INET6, RTM_GETADDR, &zns->netlink_cmd); if (ret < 0) return ret; - ret = netlink_parse_info (netlink_interface_addr, &zvrf->netlink_cmd, zvrf); + ret = netlink_parse_info (netlink_interface_addr, &zns->netlink_cmd, zns); if (ret < 0) return ret; #endif /* HAVE_IPV6 */ @@ -1247,24 +1433,24 @@ interface_lookup_netlink (struct zebra_vrf *zvrf) /* Routing table read function using netlink interface. Only called bootstrap time. */ int -netlink_route_read (struct zebra_vrf *zvrf) +netlink_route_read (struct zebra_ns *zns) { int ret; /* Get IPv4 routing table. */ - ret = netlink_request (AF_INET, RTM_GETROUTE, &zvrf->netlink_cmd); + ret = netlink_request (AF_INET, RTM_GETROUTE, &zns->netlink_cmd); if (ret < 0) return ret; - ret = netlink_parse_info (netlink_routing_table, &zvrf->netlink_cmd, zvrf); + ret = netlink_parse_info (netlink_routing_table, &zns->netlink_cmd, zns); if (ret < 0) return ret; #ifdef HAVE_IPV6 /* Get IPv6 routing table. */ - ret = netlink_request (AF_INET6, RTM_GETROUTE, &zvrf->netlink_cmd); + ret = netlink_request (AF_INET6, RTM_GETROUTE, &zns->netlink_cmd); if (ret < 0) return ret; - ret = netlink_parse_info (netlink_routing_table, &zvrf->netlink_cmd, zvrf); + ret = netlink_parse_info (netlink_routing_table, &zns->netlink_cmd, zns); if (ret < 0) return ret; #endif /* HAVE_IPV6 */ @@ -1338,16 +1524,16 @@ addattr32 (struct nlmsghdr *n, unsigned int maxlen, int type, int data) static int netlink_talk_filter (struct sockaddr_nl *snl, struct nlmsghdr *h, - vrf_id_t vrf_id) + ns_id_t ns_id) { - zlog_warn ("netlink_talk: ignoring message type 0x%04x vrf %u", h->nlmsg_type, - vrf_id); + zlog_warn ("netlink_talk: ignoring message type 0x%04x NS %u", h->nlmsg_type, + ns_id); return 0; } /* sendmsg() to netlink socket then recvmsg(). */ static int -netlink_talk (struct nlmsghdr *n, struct nlsock *nl, struct zebra_vrf *zvrf) +netlink_talk (struct nlmsghdr *n, struct nlsock *nl, struct zebra_ns *zns) { int status; struct sockaddr_nl snl; @@ -1397,7 +1583,7 @@ netlink_talk (struct nlmsghdr *n, struct nlsock *nl, struct zebra_vrf *zvrf) * Get reply from netlink socket. * The reply should either be an acknowlegement or an error. */ - return netlink_parse_info (netlink_talk_filter, nl, zvrf); + return netlink_parse_info (netlink_talk_filter, nl, zns); } /* Routing table change via netlink interface. */ @@ -1410,7 +1596,7 @@ 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 zebra_ns *zns = dzns; struct { @@ -1473,7 +1659,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, &zvrf->netlink_cmd, VRF_DEFAULT); + ret = netlink_talk (&req.n, &zns->netlink_cmd, NS_DEFAULT); if (ret < 0) return -1; @@ -1789,7 +1975,7 @@ 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 + struct zebra_ns *zns = dzns; memset(&req.n, 0, sizeof(req.n)); memset(&req.ndm, 0, sizeof(req.ndm)); @@ -1805,7 +1991,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, &zvrf->netlink_cmd, VRF_DEFAULT); + return netlink_talk (&req.n, &zns->netlink_cmd, NS_DEFAULT); } /* Routing table change via netlink interface. */ @@ -1831,6 +2017,7 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib, char buf[NL_PKT_BUF_SIZE]; } req; + struct zebra_ns *zns = dzns; struct zebra_vrf *zvrf = vrf_info_lookup (rib->vrf_id); memset (&req, 0, sizeof req - NL_PKT_BUF_SIZE); @@ -2083,7 +2270,7 @@ skip: snl.nl_family = AF_NETLINK; /* Talk to netlink socket. */ - return netlink_talk (&req.n, &zvrf->netlink_cmd, zvrf); + return netlink_talk (&req.n, &zns->netlink_cmd, zns); } int @@ -2152,7 +2339,7 @@ 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); + struct zebra_ns *zns = dzns; //vrf_info_lookup (ifp->vrf_id); p = ifc->address; memset (&req, 0, sizeof req - NL_PKT_BUF_SIZE); @@ -2186,7 +2373,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, &zvrf->netlink_cmd, zvrf); + return netlink_talk (&req.n, &zns->netlink_cmd, zns); } int @@ -2208,10 +2395,10 @@ extern struct thread_master *master; static int kernel_read (struct thread *thread) { - 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); + struct zebra_ns *zns = (struct zebra_ns *)THREAD_ARG (thread); + netlink_parse_info (netlink_information_fetch, &zns->netlink, zns); + zns->t_netlink = thread_add_read (zebrad.master, kernel_read, zns, + zns->netlink.sock); return 0; } @@ -2250,7 +2437,7 @@ static void netlink_install_filter (int sock, __u32 pid) /* Exported interface function. This function simply calls netlink_socket (). */ void -kernel_init (struct zebra_vrf *zvrf) +kernel_init (struct zebra_ns *zns) { unsigned long groups; @@ -2258,42 +2445,42 @@ kernel_init (struct zebra_vrf *zvrf) #ifdef HAVE_IPV6 groups |= RTMGRP_IPV6_ROUTE | RTMGRP_IPV6_IFADDR; #endif /* HAVE_IPV6 */ - netlink_socket (&zvrf->netlink, groups, zvrf->vrf_id); - netlink_socket (&zvrf->netlink_cmd, 0, zvrf->vrf_id); + netlink_socket (&zns->netlink, groups, zns->ns_id); + netlink_socket (&zns->netlink_cmd, 0, zns->ns_id); /* Register kernel socket. */ - if (zvrf->netlink.sock > 0) + if (zns->netlink.sock > 0) { /* Only want non-blocking on the netlink event socket */ - if (fcntl (zvrf->netlink.sock, F_SETFL, O_NONBLOCK) < 0) - zlog_err ("Can't set %s socket flags: %s", zvrf->netlink.name, + if (fcntl (zns->netlink.sock, F_SETFL, O_NONBLOCK) < 0) + zlog_err ("Can't set %s socket flags: %s", zns->netlink.name, safe_strerror (errno)); /* Set receive buffer size if it's set from command line */ if (nl_rcvbufsize) - netlink_recvbuf (&zvrf->netlink, nl_rcvbufsize); + netlink_recvbuf (&zns->netlink, nl_rcvbufsize); - 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); + netlink_install_filter (zns->netlink.sock, zns->netlink_cmd.snl.nl_pid); + zns->t_netlink = thread_add_read (zebrad.master, kernel_read, zns, + zns->netlink.sock); } } void -kernel_terminate (struct zebra_vrf *zvrf) +kernel_terminate (struct zebra_ns *zns) { - THREAD_READ_OFF (zvrf->t_netlink); + THREAD_READ_OFF (zns->t_netlink); - if (zvrf->netlink.sock >= 0) + if (zns->netlink.sock >= 0) { - close (zvrf->netlink.sock); - zvrf->netlink.sock = -1; + close (zns->netlink.sock); + zns->netlink.sock = -1; } - if (zvrf->netlink_cmd.sock >= 0) + if (zns->netlink_cmd.sock >= 0) { - close (zvrf->netlink_cmd.sock); - zvrf->netlink_cmd.sock = -1; + close (zns->netlink_cmd.sock); + zns->netlink_cmd.sock = -1; } } diff --git a/zebra/rt_netlink.h b/zebra/rt_netlink.h index d45d22f93..1d9280a29 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 interface_lookup_netlink (struct zebra_vrf *zvrf); -extern int netlink_route_read (struct zebra_vrf *zvrf); +extern int interface_lookup_netlink (struct zebra_ns *zns); +extern int netlink_route_read (struct zebra_ns *zns); #endif /* HAVE_NETLINK */ diff --git a/zebra/rtread_getmsg.c b/zebra/rtread_getmsg.c index 697539041..2c2b22879 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 (struct zebra_vrf *zvrf) +route_read (struct zebra_ns *zns) { char storage[RT_BUFSIZ]; @@ -110,10 +110,6 @@ route_read (struct zebra_vrf *zvrf) 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 5b2644979..c27e6e97f 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 (struct zebra_vrf *zvrf) +void route_read (struct zebra_ns *zns) { - netlink_route_read (zvrf); + netlink_route_read (zns); } diff --git a/zebra/rtread_sysctl.c b/zebra/rtread_sysctl.c index 2a9601a30..d74eef6c5 100644 --- a/zebra/rtread_sysctl.c +++ b/zebra/rtread_sysctl.c @@ -32,7 +32,7 @@ /* Kernel routing table read up by sysctl function. */ void -route_read (struct zebra_vrf *zvrf) +route_read (struct zebra_ns *zns) { caddr_t buf, end, ref; size_t bufsiz; @@ -49,7 +49,7 @@ route_read (struct zebra_vrf *zvrf) 0 }; - if (zvrf->vrf_id != VRF_DEFAULT) + if (zns->ns_id != NS_DEFAULT) return; /* Get buffer size. */ diff --git a/zebra/test_main.c b/zebra/test_main.c index fea673694..6639bc349 100644 --- a/zebra/test_main.c +++ b/zebra/test_main.c @@ -210,7 +210,7 @@ zebra_vrf_new (vrf_id_t vrf_id, const char *name, void **info) if (! zvrf) { - zvrf = zebra_vrf_alloc (vrf_id); + zvrf = zebra_vrf_alloc (vrf_id, name); *info = (void *)zvrf; } @@ -225,9 +225,6 @@ zebra_vrf_enable (vrf_id_t vrf_id, const char *name, void **info) assert (zvrf); - kernel_init (zvrf); - route_read (zvrf); - return 0; } @@ -252,8 +249,6 @@ zebra_vrf_disable (vrf_id_t vrf_id, const char *name, void **info) if_down (ifp); } - kernel_terminate (zvrf); - return 0; } diff --git a/zebra/zebra_ptm_redistribute.c b/zebra/zebra_ptm_redistribute.c index 741eeb8eb..8d033355f 100644 --- a/zebra/zebra_ptm_redistribute.c +++ b/zebra/zebra_ptm_redistribute.c @@ -100,7 +100,7 @@ zsend_bfd_peer_replay (int cmd, struct zserv *client) s = client->obuf; stream_reset (s); - zserv_create_header (s, cmd, VRF_DEFAULT); //Pending: + zserv_create_header (s, cmd, VRF_DEFAULT); //Pending: adjust when multi-vrf bfd work /* Write packet size. */ stream_putw_at (s, 0, stream_get_endp (s)); diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 1859661c1..3d18803b9 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -213,6 +213,9 @@ rib_nexthop_ipv4_ifindex_add (struct rib *rib, struct in_addr *ipv4, nexthop->src.ipv4 = *src; nexthop->ifindex = ifindex; ifp = if_lookup_by_index (nexthop->ifindex); + /*Pending: need to think if null ifp here is ok during bootup? + There was a crash because ifp here was coming to be NULL */ + if (ifp) if (connected_is_unnumbered(ifp)) { SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK); } @@ -1891,19 +1894,13 @@ rib_link (struct route_node *rn, struct rib *rib, int process) rib->next = head; dest->routes = rib; - /* Further processing only if entry is in main table */ - if ((rib->table == RT_TABLE_MAIN) || (rib->table == zebrad.rtm_table_default)) - { - if (process) - rib_queue_add (&zebrad, rn); - } + afi = (rn->p.family == AF_INET) ? AFI_IP : + (rn->p.family == AF_INET6) ? AFI_IP6 : AFI_MAX; + if (is_zebra_import_table_enabled (afi, rib->table)) + zebra_add_import_table_entry(rn, rib); else - { - afi = (rn->p.family == AF_INET) ? AFI_IP : - (rn->p.family == AF_INET6) ? AFI_IP6 : AFI_MAX; - if (is_zebra_import_table_enabled (afi, rib->table)) - zebra_add_import_table_entry(rn, rib); - } + if (process) + rib_queue_add (&zebrad, rn); } static void @@ -1962,14 +1959,11 @@ rib_delnode (struct route_node *rn, struct rib *rib) SET_FLAG (rib->status, RIB_ENTRY_REMOVED); - if ((rib->table == RT_TABLE_MAIN) || (rib->table == zebrad.rtm_table_default)) - rib_queue_add (&zebrad, rn); - else + afi = (rn->p.family == AF_INET) ? AFI_IP : + (rn->p.family == AF_INET6) ? AFI_IP6 : AFI_MAX; + if (is_zebra_import_table_enabled (afi, rib->table)) { - afi = (rn->p.family == AF_INET) ? AFI_IP : - (rn->p.family == AF_INET6) ? AFI_IP6 : AFI_MAX; - if (is_zebra_import_table_enabled (afi, rib->table)) - zebra_del_import_table_entry(rn, rib); + zebra_del_import_table_entry(rn, rib); /* Just clean up if non main table */ if (IS_ZEBRA_DEBUG_RIB) { @@ -1984,6 +1978,10 @@ rib_delnode (struct route_node *rn, struct rib *rib) rib_unlink(rn, rib); } + else + { + rib_queue_add (&zebrad, rn); + } } int @@ -2174,7 +2172,7 @@ void _rib_dump (const char * func, * RIB entry found by rib_lookup_ipv4_route() */ -void rib_lookup_and_dump (struct prefix_ipv4 * p) +void rib_lookup_and_dump (struct prefix_ipv4 * p, vrf_id_t vrf_id) { struct route_table *table; struct route_node *rn; @@ -2182,7 +2180,7 @@ void rib_lookup_and_dump (struct prefix_ipv4 * p) char prefix_buf[INET_ADDRSTRLEN]; /* Lookup table. */ - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); if (! table) { zlog_err ("%s: zebra_vrf_table() returned NULL", __func__); @@ -2224,14 +2222,14 @@ void rib_lookup_and_dump (struct prefix_ipv4 * p) * actions, if needed: remove such a route from FIB and deSELECT * corresponding RIB entry. Then put affected RN into RIBQ head. */ -void rib_lookup_and_pushup (struct prefix_ipv4 * p) +void rib_lookup_and_pushup (struct prefix_ipv4 * p, vrf_id_t vrf_id) { struct route_table *table; struct route_node *rn; struct rib *rib; unsigned changed = 0; - if (NULL == (table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT))) + if (NULL == (table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id))) { zlog_err ("%s: zebra_vrf_table() returned NULL", __func__); return; @@ -2591,7 +2589,7 @@ static_install_route (afi_t afi, safi_t safi, struct prefix *p, struct static_ro rib->distance = si->distance; rib->metric = 0; rib->vrf_id = si->vrf_id; - rib->table = zebrad.rtm_table_default; + rib->table = si->vrf_id ? (zebra_vrf_lookup(si->vrf_id))->table_id : zebrad.rtm_table_default; rib->nexthop_num = 0; rib->tag = si->tag; @@ -3069,7 +3067,7 @@ rib_add_ipv6_multipath (struct prefix *p, struct rib *rib, safi_t safi, if (!rib) return 0; - table = zebra_vrf_table (AFI_IP, safi, VRF_DEFAULT); + table = zebra_vrf_table (AFI_IP, safi, rib->vrf_id); if (!table) return 0; /* Make it sure prefixlen is applied to the prefix. */ @@ -3085,11 +3083,11 @@ rib_add_ipv6_multipath (struct prefix *p, struct rib *rib, safi_t safi, /* Lookup table. */ if ((table_id == RT_TABLE_MAIN) || (table_id == zebrad.rtm_table_default)) { - table = zebra_vrf_table (AFI_IP6, safi, VRF_DEFAULT); + table = zebra_vrf_table (AFI_IP6, safi, rib->vrf_id); } else { - table = zebra_vrf_other_route_table(AFI_IP6, table_id, VRF_DEFAULT); + table = zebra_vrf_other_route_table(AFI_IP6, table_id, rib->vrf_id); } if (! table) @@ -3179,6 +3177,7 @@ rib_add_ipv6_multipath (struct prefix *p, struct rib *rib, safi_t safi, } /* XXX factor with rib_delete_ipv6 */ + int rib_delete_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, struct in6_addr *gate, unsigned int ifindex, vrf_id_t vrf_id, @@ -3204,7 +3203,7 @@ rib_delete_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, } else { - table = zebra_vrf_other_route_table(AFI_IP6, table_id, VRF_DEFAULT); + table = zebra_vrf_other_route_table(AFI_IP6, table_id, vrf_id); } if (! table) return 0; @@ -3845,12 +3844,9 @@ zebra_vrf_table_create (struct zebra_vrf *zvrf, afi_t afi, safi_t safi) /* Allocate new zebra VRF. */ struct zebra_vrf * -zebra_vrf_alloc (vrf_id_t vrf_id) +zebra_vrf_alloc (vrf_id_t vrf_id, const char *name) { struct zebra_vrf *zvrf; -#ifdef HAVE_NETLINK - char nl_name[64]; -#endif zvrf = XCALLOC (MTYPE_ZEBRA_VRF, sizeof (struct zebra_vrf)); @@ -3873,16 +3869,11 @@ 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 + if (name) + { + strncpy (zvrf->name, name, strlen(name)); + zvrf->name[strlen(name)] = '\0'; + } return zvrf; } @@ -3939,12 +3930,22 @@ zebra_vrf_other_route_table (afi_t afi, u_int32_t table_id, vrf_id_t vrf_id) if (table_id >= ZEBRA_KERNEL_TABLE_MAX) return NULL; + /* Pending: This is a MUST-DO for import-table feature. + - Making it work like zebra_vrf_table() for now. Ideally, we want to + implement import table in a way, so that the other_table doesnt have to be + maintained separately. + - Need to explore how to provide import table concept + (May be only the default VRF?) + - How/if to provide some safety against picking a import table to be same as + a table associated/used in some other vrf. if (zvrf->other_table[afi][table_id] == NULL) { zvrf->other_table[afi][table_id] = route_table_init(); } - return (zvrf->other_table[afi][table_id]); + */ + + return zvrf->table[afi][SAFI_UNICAST]; } diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index 06f9f14e8..9fcef4d13 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -88,7 +88,7 @@ zebra_static_ipv4 (struct vty *vty, int add_cmd, const char *dest_str, /* VRF id */ if (vrf_id_str) - VTY_GET_INTEGER ("VRF ID", vrf_id, vrf_id_str); + VRF_GET_ID (vrf_id, vrf_id_str); //Pending: create VRF if the given vrf doesnt exist? /* Null0 static route. */ if ((gate_str != NULL) && (strncasecmp (gate_str, "Null0", strlen (gate_str)) == 0)) @@ -2030,8 +2030,12 @@ DEFUN (show_ip_route, struct route_node *rn; struct rib *rib; int first = 1; + vrf_id_t vrf_id = VRF_DEFAULT; - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); + if (argc) + VRF_GET_ID (vrf_id, argv[0]); + + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); if (! table) return CMD_SUCCESS; @@ -2056,10 +2060,23 @@ DEFUN (show_ip_nht, IP_STR "IP nexthop tracking table\n") { - zebra_print_rnh_table(0, AF_INET, vty, RNH_NEXTHOP_TYPE); + vrf_id_t vrf_id = VRF_DEFAULT; + + if (argc) + VRF_GET_ID (vrf_id, argv[0]); + + zebra_print_rnh_table(vrf_id, AF_INET, vty, RNH_NEXTHOP_TYPE); return CMD_SUCCESS; } +ALIAS (show_ip_nht, + show_ip_nht_vrf_cmd, + "show ip nht " VRF_CMD_STR, + SHOW_STR + IP_STR + "IP nexthop tracking table\n" + VRF_CMD_HELP_STR) + DEFUN (show_ipv6_nht, show_ipv6_nht_cmd, "show ipv6 nht", @@ -2067,10 +2084,23 @@ DEFUN (show_ipv6_nht, IP_STR "IPv6 nexthop tracking table\n") { - zebra_print_rnh_table(0, AF_INET6, vty, RNH_NEXTHOP_TYPE); + vrf_id_t vrf_id = VRF_DEFAULT; + + if (argc) + VRF_GET_ID (vrf_id, argv[0]); + + zebra_print_rnh_table(vrf_id, AF_INET6, vty, RNH_NEXTHOP_TYPE); return CMD_SUCCESS; } +ALIAS (show_ipv6_nht, + show_ipv6_nht_vrf_cmd, + "show ipv6 nht " VRF_CMD_STR, + SHOW_STR + IP_STR + "IPv6 nexthop tracking table\n" + VRF_CMD_HELP_STR) + DEFUN (ip_nht_default_route, ip_nht_default_route_cmd, "ip nht resolve-via-default", @@ -2206,7 +2236,7 @@ DEFUN (show_ip_route_prefix_longer, } if (argc > 1) - VTY_GET_INTEGER ("VRF ID", vrf_id, argv[1]); + VRF_GET_ID (vrf_id, argv[1]); table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); if (! table) @@ -2253,7 +2283,7 @@ DEFUN (show_ip_route_supernets, vrf_id_t vrf_id = VRF_DEFAULT; if (argc > 0) - VTY_GET_INTEGER ("VRF ID", vrf_id, argv[0]); + VRF_GET_ID (vrf_id, argv[0]); table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); if (! table) @@ -2312,7 +2342,7 @@ DEFUN (show_ip_route_protocol, } if (argc > 1) - VTY_GET_INTEGER ("VRF ID", vrf_id, argv[1]); + VRF_GET_ID (vrf_id, argv[1]); table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); if (! table) @@ -2400,7 +2430,7 @@ DEFUN (show_ip_route_addr, } if (argc > 1) - VTY_GET_INTEGER ("VRF ID", vrf_id, argv[1]); + VRF_GET_ID (vrf_id, argv[1]); table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); if (! table) @@ -2451,7 +2481,7 @@ DEFUN (show_ip_route_prefix, } if (argc > 1) - VTY_GET_INTEGER ("VRF ID", vrf_id, argv[1]); + VRF_GET_ID (vrf_id, argv[1]); table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); if (! table) @@ -2641,7 +2671,7 @@ DEFUN (show_ip_route_summary, vrf_id_t vrf_id = VRF_DEFAULT; if (argc > 0) - VTY_GET_INTEGER ("VRF ID", vrf_id, argv[0]); + VRF_GET_ID (vrf_id, argv[0]); table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); if (! table) @@ -2675,7 +2705,7 @@ DEFUN (show_ip_route_summary_prefix, vrf_id_t vrf_id = VRF_DEFAULT; if (argc > 0) - VTY_GET_INTEGER ("VRF ID", vrf_id, argv[0]); + VRF_GET_ID (vrf_id, argv[0]); table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); if (! table) @@ -3056,7 +3086,12 @@ static_config_ipv4 (struct vty *vty, safi_t safi, const char *cmd) vty_out (vty, " %d", si->distance); if (si->vrf_id != VRF_DEFAULT) - vty_out (vty, " vrf %u", si->vrf_id); + { + struct vrf *vrf; + + vrf = vrf_lookup(si->vrf_id); + vty_out (vty, " vrf %s", vrf ? vrf->name : ""); + } vty_out (vty, "%s", VTY_NEWLINE); @@ -3084,7 +3119,7 @@ DEFUN (show_ip_mroute, vrf_id_t vrf_id = VRF_DEFAULT; if (argc > 0) - VTY_GET_INTEGER ("VRF ID", vrf_id, argv[0]); + VRF_GET_ID (vrf_id, argv[0]); table = zebra_vrf_table (AFI_IP, SAFI_MULTICAST, vrf_id); if (! table) @@ -3251,7 +3286,7 @@ static_ipv6_func (struct vty *vty, int add_cmd, const char *dest_str, /* VRF id */ if (vrf_id_str) - VTY_GET_INTEGER ("VRF ID", vrf_id, vrf_id_str); + VRF_GET_ID (vrf_id, vrf_id_str); if (add_cmd) static_add_ipv6 (&p, type, gate, ifindex, flag, tag, distance, vrf_id); @@ -4459,7 +4494,7 @@ DEFUN (show_ipv6_route, vrf_id_t vrf_id = VRF_DEFAULT; if (argc > 0) - VTY_GET_INTEGER ("VRF ID", vrf_id, argv[0]); + VRF_GET_ID (vrf_id, argv[0]); table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id); if (! table) @@ -4551,7 +4586,7 @@ DEFUN (show_ipv6_route_prefix_longer, } if (argc > 1) - VTY_GET_INTEGER ("VRF ID", vrf_id, argv[1]); + VRF_GET_ID (vrf_id, argv[1]); table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id); if (! table) @@ -4605,7 +4640,7 @@ DEFUN (show_ipv6_route_protocol, } if (argc > 1) - VTY_GET_INTEGER ("VRF ID", vrf_id, argv[1]); + VRF_GET_ID (vrf_id, argv[1]); table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id); if (! table) @@ -4657,7 +4692,7 @@ DEFUN (show_ipv6_route_addr, } if (argc > 1) - VTY_GET_INTEGER ("VRF ID", vrf_id, argv[1]); + VRF_GET_ID (vrf_id, argv[1]); table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id); if (! table) @@ -4708,7 +4743,7 @@ DEFUN (show_ipv6_route_prefix, } if (argc > 1) - VTY_GET_INTEGER ("VRF ID", vrf_id, argv[1]); + VRF_GET_ID (vrf_id, argv[1]); table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id); if (! table) @@ -4750,7 +4785,7 @@ DEFUN (show_ipv6_route_summary, vrf_id_t vrf_id = VRF_DEFAULT; if (argc > 0) - VTY_GET_INTEGER ("VRF ID", vrf_id, argv[0]); + VRF_GET_ID (vrf_id, argv[0]); table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id); if (! table) @@ -4784,7 +4819,7 @@ DEFUN (show_ipv6_route_summary_prefix, vrf_id_t vrf_id = VRF_DEFAULT; if (argc > 0) - VTY_GET_INTEGER ("VRF ID", vrf_id, argv[0]); + VRF_GET_ID (vrf_id, argv[0]); table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id); if (! table) @@ -4824,7 +4859,7 @@ DEFUN (show_ipv6_mroute, vrf_id_t vrf_id = VRF_DEFAULT; if (argc > 0) - VTY_GET_INTEGER ("VRF ID", vrf_id, argv[0]); + VRF_GET_ID (vrf_id, argv[0]); table = zebra_vrf_table (AFI_IP6, SAFI_MULTICAST, vrf_id); if (! table) @@ -5232,6 +5267,31 @@ DEFUN (no_allow_external_route_update, return CMD_SUCCESS; } +/* show vrf */ +DEFUN (show_vrf, + show_vrf_cmd, + "show vrf", + SHOW_STR + "VRF\n") +{ + struct zebra_vrf *zvrf; + vrf_iter_t iter; + + for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + { + if ((zvrf = vrf_iter2info (iter)) == NULL) + continue; + if (!zvrf->vrf_id) + continue; + + vty_out (vty, "vrf %s id %u table %u%s", + zvrf->name, zvrf->vrf_id, zvrf->table_id, VTY_NEWLINE); + + } + + return CMD_SUCCESS; +} + /* Static ip route configuration write function. */ static int zebra_ip_config (struct vty *vty) @@ -5419,11 +5479,14 @@ zebra_vty_init (void) install_element (CONFIG_NODE, &no_ip_zebra_import_table_cmd); install_element (CONFIG_NODE, &no_ip_zebra_import_table_distance_cmd); + install_element (VIEW_NODE, &show_vrf_cmd); install_element (VIEW_NODE, &show_ip_route_cmd); install_element (VIEW_NODE, &show_ip_route_ospf_instance_cmd); install_element (VIEW_NODE, &show_ip_route_tag_cmd); install_element (VIEW_NODE, &show_ip_nht_cmd); + install_element (VIEW_NODE, &show_ip_nht_vrf_cmd); install_element (VIEW_NODE, &show_ipv6_nht_cmd); + install_element (VIEW_NODE, &show_ipv6_nht_vrf_cmd); install_element (VIEW_NODE, &show_ip_route_addr_cmd); install_element (VIEW_NODE, &show_ip_route_prefix_cmd); install_element (VIEW_NODE, &show_ip_route_prefix_longer_cmd); @@ -5431,11 +5494,13 @@ zebra_vty_init (void) install_element (VIEW_NODE, &show_ip_route_supernets_cmd); install_element (VIEW_NODE, &show_ip_route_summary_cmd); install_element (VIEW_NODE, &show_ip_route_summary_prefix_cmd); + install_element (ENABLE_NODE, &show_vrf_cmd); install_element (ENABLE_NODE, &show_ip_route_cmd); install_element (ENABLE_NODE, &show_ip_route_ospf_instance_cmd); install_element (ENABLE_NODE, &show_ip_route_tag_cmd); install_element (ENABLE_NODE, &show_ip_nht_cmd); - install_element (ENABLE_NODE, &show_ipv6_nht_cmd); + install_element (ENABLE_NODE, &show_ip_nht_vrf_cmd); + install_element (ENABLE_NODE, &show_ipv6_nht_vrf_cmd); install_element (ENABLE_NODE, &show_ip_route_addr_cmd); install_element (ENABLE_NODE, &show_ip_route_prefix_cmd); install_element (ENABLE_NODE, &show_ip_route_prefix_longer_cmd); diff --git a/zebra/zserv.c b/zebra/zserv.c index 9a67724f4..3f9eceae1 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -171,6 +171,16 @@ zserv_encode_interface (struct stream *s, struct interface *ifp) stream_putw_at (s, 0, stream_get_endp (s)); } +static void +zserv_encode_vrf (struct stream *s, struct vrf *vrfp) +{ + /* Interface information. */ + stream_put (s, vrfp->name, VRF_NAMSIZ); + + /* Write packet size. */ + stream_putw_at (s, 0, stream_get_endp (s)); +} + /* Interface is added. Send ZEBRA_INTERFACE_ADD to client. */ /* * This function is called in the following situations: @@ -221,6 +231,37 @@ zsend_interface_delete (struct zserv *client, struct interface *ifp) return zebra_server_send_message (client); } +int +zsend_vrf_add (struct zserv *client, struct vrf *vrfp) +{ + struct stream *s; + + s = client->obuf; + stream_reset (s); + + zserv_create_header (s, ZEBRA_VRF_ADD, vrfp->vrf_id); + zserv_encode_vrf (s, vrfp); + + client->vrfadd_cnt++; + return zebra_server_send_message(client); +} + +/* VRF deletion from zebra daemon. */ +int +zsend_vrf_delete (struct zserv *client, struct vrf *vrfp) +{ + struct stream *s; + + s = client->obuf; + stream_reset (s); + + zserv_create_header (s, ZEBRA_VRF_DELETE, vrfp->vrf_id); + zserv_encode_vrf (s, vrfp); + + client->vrfdel_cnt++; + return zebra_server_send_message (client); +} + /* Interface address is added/deleted. Send ZEBRA_INTERFACE_ADDRESS_ADD or * ZEBRA_INTERFACE_ADDRESS_DELETE to the client. * @@ -819,7 +860,7 @@ zserv_rnh_register (struct zserv *client, int sock, u_short length, p.family); return -1; } - rnh = zebra_add_rnh(&p, 0, type); + rnh = zebra_add_rnh(&p, vrf_id, type); if (type == RNH_NEXTHOP_TYPE) { if (flags && !CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED)) @@ -837,7 +878,7 @@ zserv_rnh_register (struct zserv *client, int sock, u_short length, zebra_add_rnh_client(rnh, client, type, vrf_id); /* Anything not AF_INET/INET6 has been filtered out above */ - zebra_evaluate_rnh(0, p.family, 1, type, &p); + zebra_evaluate_rnh(vrf_id, p.family, 1, type, &p); } return 0; } @@ -845,7 +886,7 @@ zserv_rnh_register (struct zserv *client, int sock, u_short length, /* Nexthop register */ static int zserv_rnh_unregister (struct zserv *client, int sock, u_short length, - rnh_type_t type) + rnh_type_t type, vrf_id_t vrf_id) { struct rnh *rnh; struct stream *s; @@ -880,7 +921,7 @@ zserv_rnh_unregister (struct zserv *client, int sock, u_short length, p.family); return -1; } - rnh = zebra_lookup_rnh(&p, 0, type); + rnh = zebra_lookup_rnh(&p, vrf_id, type); if (rnh) { client->nh_dereg_time = quagga_time(NULL); @@ -1137,7 +1178,18 @@ zread_ipv4_add (struct zserv *client, u_short length, vrf_id_t vrf_id) rib->tag = 0; /* Table */ - rib->table=zebrad.rtm_table_default; + if (vrf_id) + { + struct zebra_vrf *zvrf; + + zvrf = vrf_info_lookup (vrf_id); + if (zvrf) + rib->table = zvrf->table_id; + } + else + { + rib->table=zebrad.rtm_table_default; + } ret = rib_add_ipv4_multipath (&p, rib, safi); /* Stats */ @@ -1160,7 +1212,10 @@ zread_ipv4_delete (struct zserv *client, u_short length, vrf_id_t vrf_id) struct prefix_ipv4 p; u_char nexthop_num; u_char nexthop_type; + u_int32_t table_id; + table_id = client->rtm_table; + s = client->ibuf; ifindex = 0; nexthop.s_addr = 0; @@ -1227,8 +1282,21 @@ zread_ipv4_delete (struct zserv *client, u_short length, vrf_id_t vrf_id) else api.tag = 0; + if (vrf_id) + { + struct zebra_vrf *zvrf; + + zvrf = vrf_info_lookup (vrf_id); + if (zvrf) + table_id = zvrf->table_id; + } + else + { + table_id = client->rtm_table; + } + rib_delete_ipv4 (api.type, api.instance, api.flags, &p, nexthop_p, ifindex, - vrf_id, client->rtm_table, api.safi); + vrf_id, table_id, api.safi); client->v4_route_del_cnt++; return 0; } @@ -1265,7 +1333,7 @@ zread_ipv4_import_lookup (struct zserv *client, u_short length, #ifdef HAVE_IPV6 /* Zebra server IPv6 prefix add function. */ static int -zread_ipv4_route_ipv6_nexthop_add (struct zserv *client, u_short length) +zread_ipv4_route_ipv6_nexthop_add (struct zserv *client, u_short length, vrf_id_t vrf_id) { int i; struct stream *s; @@ -1373,7 +1441,18 @@ zread_ipv4_route_ipv6_nexthop_add (struct zserv *client, u_short length) rib->tag = 0; /* Table */ - rib->table=zebrad.rtm_table_default; + if (vrf_id) + { + struct zebra_vrf *zvrf; + + zvrf = vrf_info_lookup (vrf_id); + if (zvrf) + rib->table = zvrf->table_id; + } + else + { + rib->table=zebrad.rtm_table_default; + } ret = rib_add_ipv6_multipath ((struct prefix *)&p, rib, safi, ifindex); /* Stats */ if (ret > 0) @@ -1489,9 +1568,20 @@ zread_ipv6_add (struct zserv *client, u_short length, vrf_id_t vrf_id) else rib->tag = 0; - /* Table */ - rib->table=zebrad.rtm_table_default; rib->vrf_id = vrf_id; + /* Table */ + if (vrf_id) + { + struct zebra_vrf *zvrf; + + zvrf = vrf_info_lookup (vrf_id); + if (zvrf) + rib->table = zvrf->table_id; + } + else + { + rib->table=zebrad.rtm_table_default; + } ret = rib_add_ipv6_multipath ((struct prefix *)&p, rib, safi, ifindex); /* Stats */ if (ret > 0) @@ -1736,6 +1826,8 @@ zebra_client_create (int sock) /* Make new read thread. */ zebra_event (ZEBRA_READ, sock, client); + + zebra_vrf_update_all (client); } /* Handler of zebra service request. */ @@ -1870,7 +1962,7 @@ zebra_client_read (struct thread *thread) break; #ifdef HAVE_IPV6 case ZEBRA_IPV4_ROUTE_IPV6_NEXTHOP_ADD: - zread_ipv4_route_ipv6_nexthop_add (client, length); + zread_ipv4_route_ipv6_nexthop_add (client, length, vrf_id); break; case ZEBRA_IPV6_ROUTE_ADD: zread_ipv6_add (client, length, vrf_id); @@ -1909,13 +2001,13 @@ zebra_client_read (struct thread *thread) zserv_rnh_register(client, sock, length, RNH_NEXTHOP_TYPE, vrf_id); break; case ZEBRA_NEXTHOP_UNREGISTER: - zserv_rnh_unregister(client, sock, length, RNH_NEXTHOP_TYPE); + zserv_rnh_unregister(client, sock, length, RNH_NEXTHOP_TYPE, vrf_id); break; case ZEBRA_IMPORT_ROUTE_REGISTER: zserv_rnh_register(client, sock, length, RNH_IMPORT_CHECK_TYPE, vrf_id); break; case ZEBRA_IMPORT_ROUTE_UNREGISTER: - zserv_rnh_unregister(client, sock, length, RNH_IMPORT_CHECK_TYPE); + zserv_rnh_unregister(client, sock, length, RNH_IMPORT_CHECK_TYPE, vrf_id); break; case ZEBRA_BFD_DEST_UPDATE: case ZEBRA_BFD_DEST_REGISTER: diff --git a/zebra/zserv.h b/zebra/zserv.h index 0d23a6f61..3016428ca 100644 --- a/zebra/zserv.h +++ b/zebra/zserv.h @@ -100,6 +100,8 @@ struct zserv u_int32_t bfd_peer_upd8_cnt; u_int32_t bfd_peer_del_cnt; u_int32_t bfd_peer_replay_cnt; + u_int32_t vrfadd_cnt; + u_int32_t vrfdel_cnt; time_t connect_time; time_t last_read_time; @@ -133,14 +135,17 @@ 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 (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 interface_list (struct zebra_ns *); +extern void route_read (struct zebra_ns *); +extern void kernel_init (struct zebra_ns *); +extern void kernel_terminate (struct zebra_ns *); extern void zebra_route_map_init (void); extern void zebra_snmp_init (void); extern void zebra_vty_init (void); +extern int zsend_vrf_add (struct zserv *, struct vrf *); +extern int zsend_vrf_delete (struct zserv *, struct vrf *); + extern int zsend_interface_add (struct zserv *, struct interface *); extern int zsend_interface_delete (struct zserv *, struct interface *); extern int zsend_interface_address (int, struct zserv *, struct interface *, |