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>
This commit is contained in:
Donald Sharp 2016-02-01 10:55:42 -08:00
parent 244a59d228
commit 12f6fb9731
27 changed files with 828 additions and 220 deletions

View File

@ -443,7 +443,9 @@ struct in_pktinfo
#define ZEBRA_REDISTRIBUTE_IPV6_ADD 40 #define ZEBRA_REDISTRIBUTE_IPV6_ADD 40
#define ZEBRA_REDISTRIBUTE_IPV6_DEL 41 #define ZEBRA_REDISTRIBUTE_IPV6_DEL 41
#define ZEBRA_VRF_UNREGISTER 42 #define ZEBRA_VRF_UNREGISTER 42
#define ZEBRA_MESSAGE_MAX 43 #define ZEBRA_VRF_ADD 43
#define ZEBRA_VRF_DELETE 44
#define ZEBRA_MESSAGE_MAX 45
/* Marker value used in new Zserv, in the byte location corresponding /* Marker value used in new Zserv, in the byte location corresponding
* the command value in the old zserv header. To allow old and new * the command value in the old zserv header. To allow old and new

View File

@ -444,13 +444,11 @@ interface_info_ioctl ()
/* Lookup all interface information. */ /* Lookup all interface information. */
void void
interface_list (struct zebra_vrf *zvrf) interface_list (struct zebra_ns *zns)
{ {
if (zvrf->vrf_id != VRF_DEFAULT)
{ zlog_info ("interface_list: NS %u", zns->ns_id);
zlog_warn ("interface_list: ignore VRF %u", zvrf->vrf_id);
return;
}
/* Linux can do both proc & ioctl, ioctl is the only way to get /* Linux can do both proc & ioctl, ioctl is the only way to get
interface aliases in 2.2 series kernels. */ interface aliases in 2.2 series kernels. */
#ifdef HAVE_PROC_NET_DEV #ifdef HAVE_PROC_NET_DEV

View File

@ -351,11 +351,11 @@ interface_info_ioctl (struct interface *ifp)
/* Lookup all interface information. */ /* Lookup all interface information. */
void 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; return;
} }
interface_list_ioctl (AF_INET); interface_list_ioctl (AF_INET);

View File

@ -27,7 +27,7 @@
/* Interface information read by netlink. */ /* Interface information read by netlink. */
void void
interface_list (struct zebra_vrf *zvrf) interface_list (struct zebra_ns *zns)
{ {
interface_lookup_netlink (zvrf); interface_lookup_netlink (zns);
} }

View File

@ -93,7 +93,7 @@ ifstat_update_sysctl (void)
/* Interface listing up function using sysctl(). */ /* Interface listing up function using sysctl(). */
void void
interface_list (struct zebra_vrf *zvrf) interface_list (struct zebra_ns *zns)
{ {
caddr_t ref, buf, end; caddr_t ref, buf, end;
size_t bufsiz; size_t bufsiz;
@ -110,9 +110,9 @@ interface_list (struct zebra_vrf *zvrf)
0 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; return;
} }

View File

@ -54,6 +54,8 @@
const char *rtadv_pref_strs[] = { "medium", "high", "INVALID", "low", 0 }; const char *rtadv_pref_strs[] = { "medium", "high", "INVALID", "low", 0 };
#endif /* HAVE_RTADV */ #endif /* HAVE_RTADV */
struct zebra_ns *dzns;
/* Called when new interface is added. */ /* Called when new interface is added. */
static int static int
if_zebra_new_hook (struct interface *ifp) if_zebra_new_hook (struct interface *ifp)
@ -121,6 +123,67 @@ if_zebra_delete_hook (struct interface *ifp)
return 0; 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. */ /* Tie an interface address to its derived subnet list of addresses. */
int int
if_subnet_add (struct interface *ifp, struct connected *ifc) if_subnet_add (struct interface *ifp, struct connected *ifc)
@ -374,6 +437,8 @@ if_add_update (struct interface *ifp)
{ {
struct zebra_if *if_data; struct zebra_if *if_data;
if_link_per_ns(dzns, ifp);
if_data = ifp->info; if_data = ifp->info;
if (if_data->multicast == IF_ZEBRA_MULTICAST_ON) if (if_data->multicast == IF_ZEBRA_MULTICAST_ON)
if_set_flags (ifp, IFF_MULTICAST); if_set_flags (ifp, IFF_MULTICAST);
@ -525,6 +590,8 @@ if_delete_update (struct interface *ifp)
} }
zebra_interface_delete_update (ifp); zebra_interface_delete_update (ifp);
if_unlink_per_ns(ifp);
/* Update ifindex after distributing the delete message. This is in /* Update ifindex after distributing the delete message. This is in
case any client needs to have the old value of ifindex available case any client needs to have the old value of ifindex available
while processing the deletion. Each client daemon is responsible while processing the deletion. Each client daemon is responsible
@ -533,6 +600,52 @@ if_delete_update (struct interface *ifp)
ifp->ifindex = IFINDEX_INTERNAL; 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 static void
ipv6_ll_address_to_mac (struct in6_addr *address, u_char *mac) ipv6_ll_address_to_mac (struct in6_addr *address, u_char *mac)
{ {
@ -1043,6 +1156,34 @@ struct cmd_node interface_node =
1 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. */ /* Show all interfaces to vty. */
DEFUN (show_interface, show_interface_cmd, DEFUN (show_interface, show_interface_cmd,
"show interface", "show interface",
@ -1063,7 +1204,7 @@ DEFUN (show_interface, show_interface_cmd,
#endif /* HAVE_NET_RT_IFLIST */ #endif /* HAVE_NET_RT_IFLIST */
if (argc > 0) if (argc > 0)
VTY_GET_INTEGER ("VRF ID", vrf_id, argv[0]); VRF_GET_ID (vrf_id, argv[0]);
/* All interface print. */ /* All interface print. */
for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp)) 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 */ #endif /* HAVE_NET_RT_IFLIST */
if (argc > 1) if (argc > 1)
VTY_GET_INTEGER ("VRF ID", vrf_id, argv[1]); VRF_GET_ID (vrf_id, argv[1]);
/* Specified interface print. */ /* Specified interface print. */
ifp = if_lookup_by_name_vrf (argv[0], vrf_id); 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; vrf_id_t vrf_id = VRF_DEFAULT;
if (argc > 0) 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); if_show_description (vty, vrf_id);
@ -1874,13 +2015,15 @@ if_config_write (struct vty *vty)
struct listnode *addrnode; struct listnode *addrnode;
struct connected *ifc; struct connected *ifc;
struct prefix *p; struct prefix *p;
struct vrf *vrf;
if_data = ifp->info; if_data = ifp->info;
vrf = vrf_lookup(ifp->vrf_id);
if (ifp->vrf_id == VRF_DEFAULT) if (ifp->vrf_id == VRF_DEFAULT)
vty_out (vty, "interface %s%s", ifp->name, VTY_NEWLINE); vty_out (vty, "interface %s%s", ifp->name, VTY_NEWLINE);
else 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); VTY_NEWLINE);
if (if_data) if (if_data)
@ -1940,6 +2083,23 @@ if_config_write (struct vty *vty)
return 0; 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. */ /* Allocate and initialize interface vector. */
void void
zebra_if_init (void) zebra_if_init (void)
@ -1950,6 +2110,7 @@ zebra_if_init (void)
/* Install configuration write function. */ /* Install configuration write function. */
install_node (&interface_node, if_config_write); 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_cmd);
install_element (VIEW_NODE, &show_interface_vrf_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, &ip_address_label_cmd);
install_element (INTERFACE_NODE, &no_ip_address_label_cmd); install_element (INTERFACE_NODE, &no_ip_address_label_cmd);
#endif /* HAVE_NETLINK */ #endif /* HAVE_NETLINK */
install_element (CONFIG_NODE, &zebra_vrf_cmd);
install_element (CONFIG_NODE, &no_vrf_cmd);
install_default (VRF_NODE);
} }

View File

@ -23,6 +23,7 @@
#define _ZEBRA_INTERFACE_H #define _ZEBRA_INTERFACE_H
#include "redistribute.h" #include "redistribute.h"
#include "vrf.h"
#ifdef HAVE_IRDP #ifdef HAVE_IRDP
#include "zebra/irdp.h" #include "zebra/irdp.h"
@ -206,6 +207,10 @@ struct zebra_if
#endif /* SUNOS_5 */ #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, extern void if_nbr_ipv6ll_to_ipv4ll_neigh_update (struct interface *ifp,
struct in6_addr *address, int add); struct in6_addr *address, int add);
extern void if_nbr_ipv6ll_to_ipv4ll_neigh_del_all (struct interface *ifp); 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 if_subnet_delete (struct interface *, struct connected *);
extern int ipv6_address_configured (struct interface *ifp); 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 #ifdef HAVE_PROC_NET_DEV
extern void ifstat_update_proc (void); extern void ifstat_update_proc (void);
#endif /* HAVE_PROC_NET_DEV */ #endif /* HAVE_PROC_NET_DEV */

View File

@ -196,7 +196,7 @@ if_set_prefix (struct interface *ifp, struct connected *ifc)
struct prefix_ipv4 *p; struct prefix_ipv4 *p;
p = (struct prefix_ipv4 *) ifc->address; p = (struct prefix_ipv4 *) ifc->address;
rib_lookup_and_pushup (p); rib_lookup_and_pushup (p, ifp->vrf_id);
memset (&addreq, 0, sizeof addreq); memset (&addreq, 0, sizeof addreq);
strncpy ((char *)&addreq.ifra_name, ifp->name, sizeof addreq.ifra_name); strncpy ((char *)&addreq.ifra_name, ifp->name, sizeof addreq.ifra_name);

View File

@ -56,10 +56,10 @@ int netlink_neigh_update (int cmd, int ifindex, __u32 addr, char *lla, int llale
return 0; return 0;
} }
void kernel_init (struct zebra_vrf *zvrf) { return; } void kernel_init (struct zebra_ns *zns) { return; }
void kernel_terminate (struct zebra_vrf *zvrf) { return; } void kernel_terminate (struct zebra_ns *zns) { return; }
#ifdef HAVE_SYS_WEAK_ALIAS_PRAGMA #ifdef HAVE_SYS_WEAK_ALIAS_PRAGMA
#pragma weak route_read = kernel_init #pragma weak route_read = kernel_init
#else #else
void route_read (struct zebra_vrf *zvrf) { return; } void route_read (struct zebra_ns *zns) { return; }
#endif #endif

View File

@ -1263,11 +1263,8 @@ kernel_read (struct thread *thread)
/* Make routing socket. */ /* Make routing socket. */
static void 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) ) if ( zserv_privs.change (ZPRIVS_RAISE) )
zlog_err ("routing_socket: Can't raise privileges"); 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 /* Exported interface function. This function simply calls
routing_socket (). */ routing_socket (). */
void void
kernel_init (struct zebra_vrf *zvrf) kernel_init (struct zebra_ns *zns)
{ {
routing_socket (zvrf); routing_socket (zns);
} }
void void
kernel_terminate (struct zebra_vrf *zvrf) kernel_terminate (struct zebra_ns *zns)
{ {
return; return;
} }

View File

@ -213,16 +213,18 @@ struct quagga_signal_t zebra_signals[] =
.handler = &sigint, .handler = &sigint,
}, },
}; };
/* Callback upon creating a new VRF. */ /* Callback upon creating a new VRF. */
static int static int
zebra_vrf_new (vrf_id_t vrf_id, const char *name, void **info) zebra_vrf_new (vrf_id_t vrf_id, const char *name, void **info)
{ {
struct zebra_vrf *zvrf = *info; struct zebra_vrf *zvrf = *info;
zlog_info ("ZVRF %s with id %u", name, vrf_id);
if (! zvrf) if (! zvrf)
{ {
zvrf = zebra_vrf_alloc (vrf_id); zvrf = zebra_vrf_alloc (vrf_id, name);
*info = (void *)zvrf; *info = (void *)zvrf;
router_id_init (zvrf); router_id_init (zvrf);
} }
@ -230,6 +232,32 @@ zebra_vrf_new (vrf_id_t vrf_id, const char *name, void **info)
return 0; 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. */ /* Callback upon enabling a VRF. */
static int static int
zebra_vrf_enable (vrf_id_t vrf_id, const char *name, void **info) 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) #if defined (HAVE_RTADV)
rtadv_init (zvrf); rtadv_init (zvrf);
#endif #endif
kernel_init (zvrf);
interface_list (zvrf);
route_read (zvrf);
return 0; 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. */ /* Callback upon disabling a VRF. */
static int static int
zebra_vrf_disable (vrf_id_t vrf_id, const char *name, void **info) 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) #if defined (HAVE_RTADV)
rtadv_terminate (zvrf); rtadv_terminate (zvrf);
#endif #endif
kernel_terminate (zvrf);
list_delete_all_node (zvrf->rid_all_sorted_list); list_delete_all_node (zvrf->rid_all_sorted_list);
list_delete_all_node (zvrf->rid_lo_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 static void
zebra_vrf_init (void) zebra_vrf_init (void)
{ {
struct zebra_ns *zns;
vrf_add_hook (VRF_NEW_HOOK, zebra_vrf_new); vrf_add_hook (VRF_NEW_HOOK, zebra_vrf_new);
vrf_add_hook (VRF_ENABLE_HOOK, zebra_vrf_enable); vrf_add_hook (VRF_ENABLE_HOOK, zebra_vrf_enable);
vrf_add_hook (VRF_DISABLE_HOOK, zebra_vrf_disable); 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 (); vrf_init ();
zebra_ns_enable (0, (void **)&zns);
} }
/* Main startup routine. */ /* Main startup routine. */

View File

@ -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. */ /* Interface address addition. */
void void
zebra_interface_address_add_update (struct interface *ifp, zebra_interface_address_add_update (struct interface *ifp,

View File

@ -26,6 +26,7 @@
#include "table.h" #include "table.h"
#include "zserv.h" #include "zserv.h"
#include "vty.h" #include "vty.h"
#include "vrf.h"
extern void zebra_redistribute_add (int, struct zserv *, int, vrf_id_t); extern void zebra_redistribute_add (int, struct zserv *, int, vrf_id_t);
extern void zebra_redistribute_delete (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_up_update (struct interface *);
extern void zebra_interface_down_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_add_update (struct interface *);
extern void zebra_interface_delete_update (struct interface *); extern void zebra_interface_delete_update (struct interface *);

View File

@ -47,6 +47,11 @@ void zebra_interface_delete_update (struct interface *a)
{ return; } { return; }
#endif #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, void zebra_interface_address_add_update (struct interface *a,
struct connected *b) struct connected *b)
{ return; } { return; }

View File

@ -295,10 +295,15 @@ struct zebra_ns
/* Identifier. */ /* Identifier. */
ns_id_t ns_id; 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; struct route_table *if_table;
}; };
/* Routing table instance. */ /* Routing table instance. */
struct zebra_vrf struct zebra_vrf
{ {
@ -331,12 +336,6 @@ struct zebra_vrf
/* Routing tables off of main table for redistribute table */ /* Routing tables off of main table for redistribute table */
struct route_table *other_table[AFI_MAX][ZEBRA_KERNEL_TABLE_MAX]; 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 /* 2nd pointer type used primarily to quell a warning on
* ALL_LIST_ELEMENTS_RO * ALL_LIST_ELEMENTS_RO
*/ */
@ -356,6 +355,8 @@ struct zebra_vrf
struct zebra_ns *zns; struct zebra_ns *zns;
}; };
extern struct zebra_ns *dzns;
/* /*
* rib_table_info_t * 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 void rib_copy_nexthops (struct rib *rib, struct nexthop *nh);
extern int nexthop_has_fib_child(struct nexthop *); extern int nexthop_has_fib_child(struct nexthop *);
extern void rib_lookup_and_dump (struct prefix_ipv4 *); extern void rib_lookup_and_dump (struct prefix_ipv4 *, vrf_id_t);
extern void rib_lookup_and_pushup (struct prefix_ipv4 *); extern void rib_lookup_and_pushup (struct prefix_ipv4 *, vrf_id_t);
#define rib_dump(prefix ,rib) _rib_dump(__func__, prefix, rib) #define rib_dump(prefix ,rib) _rib_dump(__func__, prefix, rib)
extern void _rib_dump (const char *, extern void _rib_dump (const char *,
union prefix46constptr, const struct rib *); union prefix46constptr, const struct rib *);
@ -432,7 +433,7 @@ extern struct nexthop *rib_nexthop_ipv6_ifindex_add (struct rib *rib,
unsigned int ifindex); unsigned int ifindex);
extern struct zebra_vrf *zebra_vrf_lookup (vrf_id_t vrf_id); 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_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_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, extern struct route_table *zebra_vrf_other_route_table (afi_t afi, u_int32_t table_id,

View File

@ -230,7 +230,7 @@ DEFUN (router_id,
rid.family = AF_INET; rid.family = AF_INET;
if (argc > 1) 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); router_id_set (&rid, vrf_id);
@ -258,7 +258,7 @@ DEFUN (no_router_id,
rid.family = AF_INET; rid.family = AF_INET;
if (argc > 1) 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); router_id_set (&rid, vrf_id);

View File

@ -44,6 +44,7 @@
#include "zebra/redistribute.h" #include "zebra/redistribute.h"
#include "zebra/interface.h" #include "zebra/interface.h"
#include "zebra/debug.h" #include "zebra/debug.h"
#include "zebra/rtadv.h"
#include "rt_netlink.h" #include "rt_netlink.h"
@ -73,7 +74,7 @@ set_ifindex(struct interface *ifp, unsigned int ifi_index)
{ {
struct interface *oifp; 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) if (ifi_index == IFINDEX_INTERNAL)
zlog_err("Netlink is setting interface %s ifindex to reserved " 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. */ /* Make socket for Linux netlink interface. */
static int 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; int ret;
struct sockaddr_nl snl; struct sockaddr_nl snl;
@ -160,7 +161,7 @@ netlink_socket (struct nlsock *nl, unsigned long groups, vrf_id_t vrf_id)
return -1; 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) if (sock < 0)
{ {
zlog (NULL, LOG_ERR, "Can't open %s socket: %s", nl->name, 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; 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 /* Receive message from netlink interface and pass those information
to the given function. */ to the given function. */
static int static int
netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *, netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *,
vrf_id_t), ns_id_t),
struct nlsock *nl, struct zebra_vrf *zvrf) struct nlsock *nl, struct zebra_ns *zns)
{ {
int status; int status;
int ret = 0; 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 */ /* 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 && && ((msg_type == RTM_DELROUTE &&
(-errnum == ENODEV || -errnum == ESRCH)) (-errnum == ENODEV || -errnum == ESRCH))
|| (msg_type == RTM_NEWROUTE && -errnum == EEXIST))) || (msg_type == RTM_NEWROUTE && -errnum == EEXIST)))
@ -367,7 +389,7 @@ netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *,
return 0; return 0;
} }
if (nl == &zvrf->netlink_cmd if (nl == &zns->netlink_cmd
&& msg_type == RTM_NEWROUTE && -errnum == ESRCH) && msg_type == RTM_NEWROUTE && -errnum == ESRCH)
{ {
/* This is known to happen in some situations, don't log /* 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 /* skip unsolicited messages originating from command socket
* linux sets the originators port-id for {NEW|DEL}ADDR messages, * linux sets the originators port-id for {NEW|DEL}ADDR messages,
* so this has to be checked here. */ * so this has to be checked here. */
if (nl != &zvrf->netlink_cmd if (nl != &zns->netlink_cmd
&& h->nlmsg_pid == zvrf->netlink_cmd.snl.nl_pid && h->nlmsg_pid == zns->netlink_cmd.snl.nl_pid
&& (h->nlmsg_type != RTM_NEWADDR && h->nlmsg_type != RTM_DELADDR)) && (h->nlmsg_type != RTM_NEWADDR && h->nlmsg_type != RTM_DELADDR))
{ {
if (IS_ZEBRA_DEBUG_KERNEL) if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug ("netlink_parse_info: %s packet comes from %s", zlog_debug ("netlink_parse_info: %s packet comes from %s",
zvrf->netlink_cmd.name, nl->name); zns->netlink_cmd.name, nl->name);
continue; continue;
} }
error = (*filter) (&snl, h, zvrf->vrf_id); error = (*filter) (&snl, h, zns->ns_id);
if (error < 0) if (error < 0)
{ {
zlog (NULL, LOG_ERR, "%s filter function error", nl->name); 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 /* Called from interface_lookup_netlink(). This function is only used
during bootstrap. */ during bootstrap. */
static int static int
@ -518,6 +632,20 @@ netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h,
return -1; return -1;
name = (char *) RTA_DATA (tb[IFLA_IFNAME]); 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. */ /* Add interface. */
ifp = if_get_by_name_vrf (name, vrf_id); ifp = if_get_by_name_vrf (name, vrf_id);
set_ifindex(ifp, ifi->ifi_index); set_ifindex(ifp, ifi->ifi_index);
@ -537,7 +665,7 @@ netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h,
/* Lookup interface IPv4/IPv6 address. */ /* Lookup interface IPv4/IPv6 address. */
static int 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) ns_id_t ns_id)
{ {
int len; int len;
struct ifaddrmsg *ifa; struct ifaddrmsg *ifa;
@ -548,6 +676,8 @@ netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h,
u_char flags = 0; u_char flags = 0;
char *label = NULL; char *label = NULL;
vrf_id_t vrf_id = ns_id;
ifa = NLMSG_DATA (h); ifa = NLMSG_DATA (h);
if (ifa->ifa_family != AF_INET 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); memset (tb, 0, sizeof tb);
netlink_parse_rtattr (tb, IFA_MAX, IFA_RTA (ifa), len); 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) if (ifp == NULL)
{ {
zlog_err ("netlink_interface_addr can't find interface by index %d vrf %u", 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)) if (!is_zebra_valid_kernel_table(table) && !is_zebra_main_routing_table(table))
return 0; return 0;
vrf_id = vrf_lookup_by_table(table);
len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg)); len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg));
if (len < 0) if (len < 0)
return -1; return -1;
@ -854,7 +986,7 @@ static const struct message rtproto_str[] = {
/* Routing information change from the kernel. */ /* Routing information change from the kernel. */
static int 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) ns_id_t ns_id)
{ {
int len; int len;
struct rtmsg *rtm; struct rtmsg *rtm;
@ -871,6 +1003,8 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h,
void *gate; void *gate;
void *src; void *src;
vrf_id_t vrf_id = ns_id;
rtm = NLMSG_DATA (h); rtm = NLMSG_DATA (h);
if (!(h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE)) 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)) if (!is_zebra_valid_kernel_table(table) && !is_zebra_main_routing_table(table))
return 0; return 0;
vrf_id = vrf_lookup_by_table(table);
len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg)); len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg));
if (len < 0) if (len < 0)
return -1; return -1;
@ -1062,13 +1198,17 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h,
static int 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) ns_id_t ns_id)
{ {
int len; int len;
struct ifinfomsg *ifi; struct ifinfomsg *ifi;
struct rtattr *tb[IFLA_MAX + 1]; struct rtattr *tb[IFLA_MAX + 1];
struct interface *ifp; struct interface *ifp;
char *name; char *name;
struct connected *ifc;
struct listnode *node;
vrf_id_t vrf_id = ns_id;
ifi = NLMSG_DATA (h); ifi = NLMSG_DATA (h);
@ -1106,21 +1246,58 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h,
return -1; return -1;
name = (char *) RTA_DATA (tb[IFLA_IFNAME]); 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. */ /* Add interface. */
if (h->nlmsg_type == RTM_NEWLINK) 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) if (ifp == NULL)
ifp = if_get_by_name_vrf (name, vrf_id); 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); set_ifindex(ifp, ifi->ifi_index);
ifp->flags = ifi->ifi_flags & 0x0000fffff; ifp->flags = ifi->ifi_flags & 0x0000fffff;
ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]); ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]);
ifp->metric = 0; 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); netlink_interface_update_hw_addr (tb, ifp);
/* If new link is added. */ /* 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->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]);
ifp->metric = 0; 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); netlink_interface_update_hw_addr (tb, ifp);
if (if_is_no_ptm_operative (ifp)) if (if_is_no_ptm_operative (ifp))
@ -1154,6 +1337,9 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h,
} }
else else
{ {
if (tb[IFLA_MASTER])
vrf_id = *(u_int32_t *)RTA_DATA(tb[IFLA_MASTER]);
/* RTM_DELLINK. */ /* RTM_DELLINK. */
ifp = if_lookup_by_name_vrf (name, vrf_id); 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 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) ns_id_t ns_id)
{ {
/* JF: Ignore messages that aren't from the kernel */ /* JF: Ignore messages that aren't from the kernel */
if ( snl->nl_pid != 0 ) if ( snl->nl_pid != 0 )
@ -1184,26 +1370,26 @@ netlink_information_fetch (struct sockaddr_nl *snl, struct nlmsghdr *h,
switch (h->nlmsg_type) switch (h->nlmsg_type)
{ {
case RTM_NEWROUTE: case RTM_NEWROUTE:
return netlink_route_change (snl, h, vrf_id); return netlink_route_change (snl, h, ns_id);
break; break;
case RTM_DELROUTE: case RTM_DELROUTE:
return netlink_route_change (snl, h, vrf_id); return netlink_route_change (snl, h, ns_id);
break; break;
case RTM_NEWLINK: case RTM_NEWLINK:
return netlink_link_change (snl, h, vrf_id); return netlink_link_change (snl, h, ns_id);
break; break;
case RTM_DELLINK: case RTM_DELLINK:
return netlink_link_change (snl, h, vrf_id); return netlink_link_change (snl, h, ns_id);
break; break;
case RTM_NEWADDR: case RTM_NEWADDR:
return netlink_interface_addr (snl, h, vrf_id); return netlink_interface_addr (snl, h, ns_id);
break; break;
case RTM_DELADDR: case RTM_DELADDR:
return netlink_interface_addr (snl, h, vrf_id); return netlink_interface_addr (snl, h, ns_id);
break; break;
default: default:
zlog_warn ("Unknown netlink nlmsg_type %d vrf %u\n", h->nlmsg_type, zlog_warn ("Unknown netlink nlmsg_type %d vrf %u\n", h->nlmsg_type,
vrf_id); ns_id);
break; break;
} }
return 0; return 0;
@ -1211,32 +1397,32 @@ netlink_information_fetch (struct sockaddr_nl *snl, struct nlmsghdr *h,
/* Interface lookup by netlink socket. */ /* Interface lookup by netlink socket. */
int int
interface_lookup_netlink (struct zebra_vrf *zvrf) interface_lookup_netlink (struct zebra_ns *zns)
{ {
int ret; int ret;
/* Get interface information. */ /* 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) if (ret < 0)
return ret; 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) if (ret < 0)
return ret; return ret;
/* Get IPv4 address of the interfaces. */ /* 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) if (ret < 0)
return ret; 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) if (ret < 0)
return ret; return ret;
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
/* Get IPv6 address of the interfaces. */ /* 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) if (ret < 0)
return ret; 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) if (ret < 0)
return ret; return ret;
#endif /* HAVE_IPV6 */ #endif /* HAVE_IPV6 */
@ -1247,24 +1433,24 @@ interface_lookup_netlink (struct zebra_vrf *zvrf)
/* Routing table read function using netlink interface. Only called /* Routing table read function using netlink interface. Only called
bootstrap time. */ bootstrap time. */
int int
netlink_route_read (struct zebra_vrf *zvrf) netlink_route_read (struct zebra_ns *zns)
{ {
int ret; int ret;
/* Get IPv4 routing table. */ /* 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) if (ret < 0)
return ret; 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) if (ret < 0)
return ret; return ret;
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
/* Get IPv6 routing table. */ /* 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) if (ret < 0)
return ret; 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) if (ret < 0)
return ret; return ret;
#endif /* HAVE_IPV6 */ #endif /* HAVE_IPV6 */
@ -1338,16 +1524,16 @@ addattr32 (struct nlmsghdr *n, unsigned int maxlen, int type, int data)
static int 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) ns_id_t ns_id)
{ {
zlog_warn ("netlink_talk: ignoring message type 0x%04x vrf %u", h->nlmsg_type, zlog_warn ("netlink_talk: ignoring message type 0x%04x NS %u", h->nlmsg_type,
vrf_id); ns_id);
return 0; return 0;
} }
/* sendmsg() to netlink socket then recvmsg(). */ /* sendmsg() to netlink socket then recvmsg(). */
static int 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; int status;
struct sockaddr_nl snl; 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. * Get reply from netlink socket.
* The reply should either be an acknowlegement or an error. * 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. */ /* 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; struct sockaddr_nl snl;
int discard; int discard;
struct zebra_vrf *zvrf = vrf_info_lookup (VRF_DEFAULT); //Pending struct zebra_ns *zns = dzns;
struct struct
{ {
@ -1473,7 +1659,7 @@ netlink_route (int cmd, int family, void *dest, int length, void *gate,
snl.nl_family = AF_NETLINK; snl.nl_family = AF_NETLINK;
/* Talk to netlink socket. */ /* 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) if (ret < 0)
return -1; return -1;
@ -1789,7 +1975,7 @@ netlink_neigh_update (int cmd, int ifindex, __u32 addr, char *lla, int llalen)
char buf[256]; char buf[256];
} req; } 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.n, 0, sizeof(req.n));
memset(&req.ndm, 0, sizeof(req.ndm)); 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_DST, &addr, 4);
addattr_l(&req.n, sizeof(req), NDA_LLADDR, lla, llalen); 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. */ /* 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]; char buf[NL_PKT_BUF_SIZE];
} req; } req;
struct zebra_ns *zns = dzns;
struct zebra_vrf *zvrf = vrf_info_lookup (rib->vrf_id); struct zebra_vrf *zvrf = vrf_info_lookup (rib->vrf_id);
memset (&req, 0, sizeof req - NL_PKT_BUF_SIZE); memset (&req, 0, sizeof req - NL_PKT_BUF_SIZE);
@ -2083,7 +2270,7 @@ skip:
snl.nl_family = AF_NETLINK; snl.nl_family = AF_NETLINK;
/* Talk to netlink socket. */ /* Talk to netlink socket. */
return netlink_talk (&req.n, &zvrf->netlink_cmd, zvrf); return netlink_talk (&req.n, &zns->netlink_cmd, zns);
} }
int int
@ -2152,7 +2339,7 @@ netlink_address (int cmd, int family, struct interface *ifp,
char buf[NL_PKT_BUF_SIZE]; char buf[NL_PKT_BUF_SIZE];
} req; } 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; p = ifc->address;
memset (&req, 0, sizeof req - NL_PKT_BUF_SIZE); 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, addattr_l (&req.n, sizeof req, IFA_LABEL, ifc->label,
strlen (ifc->label) + 1); strlen (ifc->label) + 1);
return netlink_talk (&req.n, &zvrf->netlink_cmd, zvrf); return netlink_talk (&req.n, &zns->netlink_cmd, zns);
} }
int int
@ -2208,10 +2395,10 @@ extern struct thread_master *master;
static int static int
kernel_read (struct thread *thread) kernel_read (struct thread *thread)
{ {
struct zebra_vrf *zvrf = (struct zebra_vrf *)THREAD_ARG (thread); struct zebra_ns *zns = (struct zebra_ns *)THREAD_ARG (thread);
netlink_parse_info (netlink_information_fetch, &zvrf->netlink, zvrf); netlink_parse_info (netlink_information_fetch, &zns->netlink, zns);
zvrf->t_netlink = thread_add_read (zebrad.master, kernel_read, zvrf, zns->t_netlink = thread_add_read (zebrad.master, kernel_read, zns,
zvrf->netlink.sock); zns->netlink.sock);
return 0; return 0;
} }
@ -2250,7 +2437,7 @@ static void netlink_install_filter (int sock, __u32 pid)
/* Exported interface function. This function simply calls /* Exported interface function. This function simply calls
netlink_socket (). */ netlink_socket (). */
void void
kernel_init (struct zebra_vrf *zvrf) kernel_init (struct zebra_ns *zns)
{ {
unsigned long groups; unsigned long groups;
@ -2258,42 +2445,42 @@ kernel_init (struct zebra_vrf *zvrf)
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
groups |= RTMGRP_IPV6_ROUTE | RTMGRP_IPV6_IFADDR; groups |= RTMGRP_IPV6_ROUTE | RTMGRP_IPV6_IFADDR;
#endif /* HAVE_IPV6 */ #endif /* HAVE_IPV6 */
netlink_socket (&zvrf->netlink, groups, zvrf->vrf_id); netlink_socket (&zns->netlink, groups, zns->ns_id);
netlink_socket (&zvrf->netlink_cmd, 0, zvrf->vrf_id); netlink_socket (&zns->netlink_cmd, 0, zns->ns_id);
/* Register kernel socket. */ /* Register kernel socket. */
if (zvrf->netlink.sock > 0) if (zns->netlink.sock > 0)
{ {
/* Only want non-blocking on the netlink event socket */ /* Only want non-blocking on the netlink event socket */
if (fcntl (zvrf->netlink.sock, F_SETFL, O_NONBLOCK) < 0) if (fcntl (zns->netlink.sock, F_SETFL, O_NONBLOCK) < 0)
zlog_err ("Can't set %s socket flags: %s", zvrf->netlink.name, zlog_err ("Can't set %s socket flags: %s", zns->netlink.name,
safe_strerror (errno)); safe_strerror (errno));
/* Set receive buffer size if it's set from command line */ /* Set receive buffer size if it's set from command line */
if (nl_rcvbufsize) 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); netlink_install_filter (zns->netlink.sock, zns->netlink_cmd.snl.nl_pid);
zvrf->t_netlink = thread_add_read (zebrad.master, kernel_read, zvrf, zns->t_netlink = thread_add_read (zebrad.master, kernel_read, zns,
zvrf->netlink.sock); zns->netlink.sock);
} }
} }
void 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); close (zns->netlink.sock);
zvrf->netlink.sock = -1; zns->netlink.sock = -1;
} }
if (zvrf->netlink_cmd.sock >= 0) if (zns->netlink_cmd.sock >= 0)
{ {
close (zvrf->netlink_cmd.sock); close (zns->netlink_cmd.sock);
zvrf->netlink_cmd.sock = -1; zns->netlink_cmd.sock = -1;
} }
} }

View File

@ -44,8 +44,8 @@ nl_rtproto_to_str (u_char rtproto);
int int
netlink_neigh_update (int cmd, int ifindex, __u32 addr, char *lla, int llalen); netlink_neigh_update (int cmd, int ifindex, __u32 addr, char *lla, int llalen);
extern int interface_lookup_netlink (struct zebra_vrf *zvrf); extern int interface_lookup_netlink (struct zebra_ns *zns);
extern int netlink_route_read (struct zebra_vrf *zvrf); extern int netlink_route_read (struct zebra_ns *zns);
#endif /* HAVE_NETLINK */ #endif /* HAVE_NETLINK */

View File

@ -95,7 +95,7 @@ handle_route_entry (mib2_ipRouteEntry_t *routeEntry)
} }
void void
route_read (struct zebra_vrf *zvrf) route_read (struct zebra_ns *zns)
{ {
char storage[RT_BUFSIZ]; char storage[RT_BUFSIZ];
@ -110,10 +110,6 @@ route_read (struct zebra_vrf *zvrf)
struct strbuf msgdata; struct strbuf msgdata;
int flags, dev, retval, process; int flags, dev, retval, process;
if (zvrf->vrf_id != VRF_DEFAULT) {
return;
}
if ((dev = open (_PATH_GETMSG_ROUTE, O_RDWR)) == -1) { if ((dev = open (_PATH_GETMSG_ROUTE, O_RDWR)) == -1) {
zlog_warn ("can't open %s: %s", _PATH_GETMSG_ROUTE, zlog_warn ("can't open %s: %s", _PATH_GETMSG_ROUTE,
safe_strerror (errno)); safe_strerror (errno));

View File

@ -25,7 +25,7 @@
#include "zebra/zserv.h" #include "zebra/zserv.h"
#include "zebra/rt_netlink.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);
} }

View File

@ -32,7 +32,7 @@
/* Kernel routing table read up by sysctl function. */ /* Kernel routing table read up by sysctl function. */
void void
route_read (struct zebra_vrf *zvrf) route_read (struct zebra_ns *zns)
{ {
caddr_t buf, end, ref; caddr_t buf, end, ref;
size_t bufsiz; size_t bufsiz;
@ -49,7 +49,7 @@ route_read (struct zebra_vrf *zvrf)
0 0
}; };
if (zvrf->vrf_id != VRF_DEFAULT) if (zns->ns_id != NS_DEFAULT)
return; return;
/* Get buffer size. */ /* Get buffer size. */

View File

@ -210,7 +210,7 @@ zebra_vrf_new (vrf_id_t vrf_id, const char *name, void **info)
if (! zvrf) if (! zvrf)
{ {
zvrf = zebra_vrf_alloc (vrf_id); zvrf = zebra_vrf_alloc (vrf_id, name);
*info = (void *)zvrf; *info = (void *)zvrf;
} }
@ -225,9 +225,6 @@ zebra_vrf_enable (vrf_id_t vrf_id, const char *name, void **info)
assert (zvrf); assert (zvrf);
kernel_init (zvrf);
route_read (zvrf);
return 0; return 0;
} }
@ -252,8 +249,6 @@ zebra_vrf_disable (vrf_id_t vrf_id, const char *name, void **info)
if_down (ifp); if_down (ifp);
} }
kernel_terminate (zvrf);
return 0; return 0;
} }

View File

@ -100,7 +100,7 @@ zsend_bfd_peer_replay (int cmd, struct zserv *client)
s = client->obuf; s = client->obuf;
stream_reset (s); 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. */ /* Write packet size. */
stream_putw_at (s, 0, stream_get_endp (s)); stream_putw_at (s, 0, stream_get_endp (s));

View File

@ -213,6 +213,9 @@ rib_nexthop_ipv4_ifindex_add (struct rib *rib, struct in_addr *ipv4,
nexthop->src.ipv4 = *src; nexthop->src.ipv4 = *src;
nexthop->ifindex = ifindex; nexthop->ifindex = ifindex;
ifp = if_lookup_by_index (nexthop->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)) { if (connected_is_unnumbered(ifp)) {
SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK); 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; rib->next = head;
dest->routes = rib; dest->routes = rib;
/* Further processing only if entry is in main table */ afi = (rn->p.family == AF_INET) ? AFI_IP :
if ((rib->table == RT_TABLE_MAIN) || (rib->table == zebrad.rtm_table_default)) (rn->p.family == AF_INET6) ? AFI_IP6 : AFI_MAX;
{ if (is_zebra_import_table_enabled (afi, rib->table))
if (process) zebra_add_import_table_entry(rn, rib);
rib_queue_add (&zebrad, rn);
}
else else
{ if (process)
afi = (rn->p.family == AF_INET) ? AFI_IP : rib_queue_add (&zebrad, rn);
(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);
}
} }
static void static void
@ -1962,14 +1959,11 @@ rib_delnode (struct route_node *rn, struct rib *rib)
SET_FLAG (rib->status, RIB_ENTRY_REMOVED); SET_FLAG (rib->status, RIB_ENTRY_REMOVED);
if ((rib->table == RT_TABLE_MAIN) || (rib->table == zebrad.rtm_table_default)) afi = (rn->p.family == AF_INET) ? AFI_IP :
rib_queue_add (&zebrad, rn); (rn->p.family == AF_INET6) ? AFI_IP6 : AFI_MAX;
else if (is_zebra_import_table_enabled (afi, rib->table))
{ {
afi = (rn->p.family == AF_INET) ? AFI_IP : zebra_del_import_table_entry(rn, rib);
(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);
/* Just clean up if non main table */ /* Just clean up if non main table */
if (IS_ZEBRA_DEBUG_RIB) if (IS_ZEBRA_DEBUG_RIB)
{ {
@ -1984,6 +1978,10 @@ rib_delnode (struct route_node *rn, struct rib *rib)
rib_unlink(rn, rib); rib_unlink(rn, rib);
} }
else
{
rib_queue_add (&zebrad, rn);
}
} }
int int
@ -2174,7 +2172,7 @@ void _rib_dump (const char * func,
* RIB entry found by rib_lookup_ipv4_route() * 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_table *table;
struct route_node *rn; struct route_node *rn;
@ -2182,7 +2180,7 @@ void rib_lookup_and_dump (struct prefix_ipv4 * p)
char prefix_buf[INET_ADDRSTRLEN]; char prefix_buf[INET_ADDRSTRLEN];
/* Lookup table. */ /* Lookup table. */
table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id);
if (! table) if (! table)
{ {
zlog_err ("%s: zebra_vrf_table() returned NULL", __func__); 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 * actions, if needed: remove such a route from FIB and deSELECT
* corresponding RIB entry. Then put affected RN into RIBQ head. * 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_table *table;
struct route_node *rn; struct route_node *rn;
struct rib *rib; struct rib *rib;
unsigned changed = 0; 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__); zlog_err ("%s: zebra_vrf_table() returned NULL", __func__);
return; 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->distance = si->distance;
rib->metric = 0; rib->metric = 0;
rib->vrf_id = si->vrf_id; 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->nexthop_num = 0;
rib->tag = si->tag; rib->tag = si->tag;
@ -3069,7 +3067,7 @@ rib_add_ipv6_multipath (struct prefix *p, struct rib *rib, safi_t safi,
if (!rib) if (!rib)
return 0; return 0;
table = zebra_vrf_table (AFI_IP, safi, VRF_DEFAULT); table = zebra_vrf_table (AFI_IP, safi, rib->vrf_id);
if (!table) if (!table)
return 0; return 0;
/* Make it sure prefixlen is applied to the prefix. */ /* 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. */ /* Lookup table. */
if ((table_id == RT_TABLE_MAIN) || (table_id == zebrad.rtm_table_default)) 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 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) 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 */ /* XXX factor with rib_delete_ipv6 */
int int
rib_delete_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, 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, 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 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) if (! table)
return 0; return 0;
@ -3845,12 +3844,9 @@ zebra_vrf_table_create (struct zebra_vrf *zvrf, afi_t afi, safi_t safi)
/* Allocate new zebra VRF. */ /* Allocate new zebra VRF. */
struct 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; struct zebra_vrf *zvrf;
#ifdef HAVE_NETLINK
char nl_name[64];
#endif
zvrf = XCALLOC (MTYPE_ZEBRA_VRF, sizeof (struct zebra_vrf)); zvrf = XCALLOC (MTYPE_ZEBRA_VRF, sizeof (struct zebra_vrf));
@ -3873,16 +3869,11 @@ zebra_vrf_alloc (vrf_id_t vrf_id)
/* Set VRF ID */ /* Set VRF ID */
zvrf->vrf_id = vrf_id; zvrf->vrf_id = vrf_id;
#ifdef HAVE_NETLINK if (name)
/* Initialize netlink sockets */ {
snprintf (nl_name, 64, "netlink-listen (vrf %u)", vrf_id); strncpy (zvrf->name, name, strlen(name));
zvrf->netlink.sock = -1; zvrf->name[strlen(name)] = '\0';
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; 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) if (table_id >= ZEBRA_KERNEL_TABLE_MAX)
return NULL; 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) if (zvrf->other_table[afi][table_id] == NULL)
{ {
zvrf->other_table[afi][table_id] = route_table_init(); zvrf->other_table[afi][table_id] = route_table_init();
} }
return (zvrf->other_table[afi][table_id]); return (zvrf->other_table[afi][table_id]);
*/
return zvrf->table[afi][SAFI_UNICAST];
} }

View File

@ -88,7 +88,7 @@ zebra_static_ipv4 (struct vty *vty, int add_cmd, const char *dest_str,
/* VRF id */ /* VRF id */
if (vrf_id_str) 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. */ /* Null0 static route. */
if ((gate_str != NULL) && (strncasecmp (gate_str, "Null0", strlen (gate_str)) == 0)) 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 route_node *rn;
struct rib *rib; struct rib *rib;
int first = 1; 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) if (! table)
return CMD_SUCCESS; return CMD_SUCCESS;
@ -2056,10 +2060,23 @@ DEFUN (show_ip_nht,
IP_STR IP_STR
"IP nexthop tracking table\n") "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; 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, DEFUN (show_ipv6_nht,
show_ipv6_nht_cmd, show_ipv6_nht_cmd,
"show ipv6 nht", "show ipv6 nht",
@ -2067,10 +2084,23 @@ DEFUN (show_ipv6_nht,
IP_STR IP_STR
"IPv6 nexthop tracking table\n") "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; 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, DEFUN (ip_nht_default_route,
ip_nht_default_route_cmd, ip_nht_default_route_cmd,
"ip nht resolve-via-default", "ip nht resolve-via-default",
@ -2206,7 +2236,7 @@ DEFUN (show_ip_route_prefix_longer,
} }
if (argc > 1) 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); table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id);
if (! table) if (! table)
@ -2253,7 +2283,7 @@ DEFUN (show_ip_route_supernets,
vrf_id_t vrf_id = VRF_DEFAULT; vrf_id_t vrf_id = VRF_DEFAULT;
if (argc > 0) 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); table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id);
if (! table) if (! table)
@ -2312,7 +2342,7 @@ DEFUN (show_ip_route_protocol,
} }
if (argc > 1) 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); table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id);
if (! table) if (! table)
@ -2400,7 +2430,7 @@ DEFUN (show_ip_route_addr,
} }
if (argc > 1) 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); table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id);
if (! table) if (! table)
@ -2451,7 +2481,7 @@ DEFUN (show_ip_route_prefix,
} }
if (argc > 1) 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); table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id);
if (! table) if (! table)
@ -2641,7 +2671,7 @@ DEFUN (show_ip_route_summary,
vrf_id_t vrf_id = VRF_DEFAULT; vrf_id_t vrf_id = VRF_DEFAULT;
if (argc > 0) 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); table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id);
if (! table) if (! table)
@ -2675,7 +2705,7 @@ DEFUN (show_ip_route_summary_prefix,
vrf_id_t vrf_id = VRF_DEFAULT; vrf_id_t vrf_id = VRF_DEFAULT;
if (argc > 0) 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); table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id);
if (! table) if (! table)
@ -3056,7 +3086,12 @@ static_config_ipv4 (struct vty *vty, safi_t safi, const char *cmd)
vty_out (vty, " %d", si->distance); vty_out (vty, " %d", si->distance);
if (si->vrf_id != VRF_DEFAULT) 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); vty_out (vty, "%s", VTY_NEWLINE);
@ -3084,7 +3119,7 @@ DEFUN (show_ip_mroute,
vrf_id_t vrf_id = VRF_DEFAULT; vrf_id_t vrf_id = VRF_DEFAULT;
if (argc > 0) 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); table = zebra_vrf_table (AFI_IP, SAFI_MULTICAST, vrf_id);
if (! table) if (! table)
@ -3251,7 +3286,7 @@ static_ipv6_func (struct vty *vty, int add_cmd, const char *dest_str,
/* VRF id */ /* VRF id */
if (vrf_id_str) 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) if (add_cmd)
static_add_ipv6 (&p, type, gate, ifindex, flag, tag, distance, vrf_id); 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; vrf_id_t vrf_id = VRF_DEFAULT;
if (argc > 0) 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); table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id);
if (! table) if (! table)
@ -4551,7 +4586,7 @@ DEFUN (show_ipv6_route_prefix_longer,
} }
if (argc > 1) 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); table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id);
if (! table) if (! table)
@ -4605,7 +4640,7 @@ DEFUN (show_ipv6_route_protocol,
} }
if (argc > 1) 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); table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id);
if (! table) if (! table)
@ -4657,7 +4692,7 @@ DEFUN (show_ipv6_route_addr,
} }
if (argc > 1) 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); table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id);
if (! table) if (! table)
@ -4708,7 +4743,7 @@ DEFUN (show_ipv6_route_prefix,
} }
if (argc > 1) 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); table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id);
if (! table) if (! table)
@ -4750,7 +4785,7 @@ DEFUN (show_ipv6_route_summary,
vrf_id_t vrf_id = VRF_DEFAULT; vrf_id_t vrf_id = VRF_DEFAULT;
if (argc > 0) 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); table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id);
if (! table) if (! table)
@ -4784,7 +4819,7 @@ DEFUN (show_ipv6_route_summary_prefix,
vrf_id_t vrf_id = VRF_DEFAULT; vrf_id_t vrf_id = VRF_DEFAULT;
if (argc > 0) 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); table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id);
if (! table) if (! table)
@ -4824,7 +4859,7 @@ DEFUN (show_ipv6_mroute,
vrf_id_t vrf_id = VRF_DEFAULT; vrf_id_t vrf_id = VRF_DEFAULT;
if (argc > 0) 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); table = zebra_vrf_table (AFI_IP6, SAFI_MULTICAST, vrf_id);
if (! table) if (! table)
@ -5232,6 +5267,31 @@ DEFUN (no_allow_external_route_update,
return CMD_SUCCESS; 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 ip route configuration write function. */
static int static int
zebra_ip_config (struct vty *vty) 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_cmd);
install_element (CONFIG_NODE, &no_ip_zebra_import_table_distance_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_cmd);
install_element (VIEW_NODE, &show_ip_route_ospf_instance_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_route_tag_cmd);
install_element (VIEW_NODE, &show_ip_nht_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_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_addr_cmd);
install_element (VIEW_NODE, &show_ip_route_prefix_cmd); install_element (VIEW_NODE, &show_ip_route_prefix_cmd);
install_element (VIEW_NODE, &show_ip_route_prefix_longer_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_supernets_cmd);
install_element (VIEW_NODE, &show_ip_route_summary_cmd); install_element (VIEW_NODE, &show_ip_route_summary_cmd);
install_element (VIEW_NODE, &show_ip_route_summary_prefix_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_cmd);
install_element (ENABLE_NODE, &show_ip_route_ospf_instance_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_route_tag_cmd);
install_element (ENABLE_NODE, &show_ip_nht_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_addr_cmd);
install_element (ENABLE_NODE, &show_ip_route_prefix_cmd); install_element (ENABLE_NODE, &show_ip_route_prefix_cmd);
install_element (ENABLE_NODE, &show_ip_route_prefix_longer_cmd); install_element (ENABLE_NODE, &show_ip_route_prefix_longer_cmd);

View File

@ -171,6 +171,16 @@ zserv_encode_interface (struct stream *s, struct interface *ifp)
stream_putw_at (s, 0, stream_get_endp (s)); 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. */ /* Interface is added. Send ZEBRA_INTERFACE_ADD to client. */
/* /*
* This function is called in the following situations: * 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); 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 /* Interface address is added/deleted. Send ZEBRA_INTERFACE_ADDRESS_ADD or
* ZEBRA_INTERFACE_ADDRESS_DELETE to the client. * ZEBRA_INTERFACE_ADDRESS_DELETE to the client.
* *
@ -819,7 +860,7 @@ zserv_rnh_register (struct zserv *client, int sock, u_short length,
p.family); p.family);
return -1; return -1;
} }
rnh = zebra_add_rnh(&p, 0, type); rnh = zebra_add_rnh(&p, vrf_id, type);
if (type == RNH_NEXTHOP_TYPE) if (type == RNH_NEXTHOP_TYPE)
{ {
if (flags && !CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED)) 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); zebra_add_rnh_client(rnh, client, type, vrf_id);
/* Anything not AF_INET/INET6 has been filtered out above */ /* 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; return 0;
} }
@ -845,7 +886,7 @@ zserv_rnh_register (struct zserv *client, int sock, u_short length,
/* Nexthop register */ /* Nexthop register */
static int static int
zserv_rnh_unregister (struct zserv *client, int sock, u_short length, 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 rnh *rnh;
struct stream *s; struct stream *s;
@ -880,7 +921,7 @@ zserv_rnh_unregister (struct zserv *client, int sock, u_short length,
p.family); p.family);
return -1; return -1;
} }
rnh = zebra_lookup_rnh(&p, 0, type); rnh = zebra_lookup_rnh(&p, vrf_id, type);
if (rnh) if (rnh)
{ {
client->nh_dereg_time = quagga_time(NULL); 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; rib->tag = 0;
/* Table */ /* 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); ret = rib_add_ipv4_multipath (&p, rib, safi);
/* Stats */ /* Stats */
@ -1160,7 +1212,10 @@ zread_ipv4_delete (struct zserv *client, u_short length, vrf_id_t vrf_id)
struct prefix_ipv4 p; struct prefix_ipv4 p;
u_char nexthop_num; u_char nexthop_num;
u_char nexthop_type; u_char nexthop_type;
u_int32_t table_id;
table_id = client->rtm_table;
s = client->ibuf; s = client->ibuf;
ifindex = 0; ifindex = 0;
nexthop.s_addr = 0; nexthop.s_addr = 0;
@ -1227,8 +1282,21 @@ zread_ipv4_delete (struct zserv *client, u_short length, vrf_id_t vrf_id)
else else
api.tag = 0; 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, 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++; client->v4_route_del_cnt++;
return 0; return 0;
} }
@ -1265,7 +1333,7 @@ zread_ipv4_import_lookup (struct zserv *client, u_short length,
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
/* Zebra server IPv6 prefix add function. */ /* Zebra server IPv6 prefix add function. */
static int 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; int i;
struct stream *s; struct stream *s;
@ -1373,7 +1441,18 @@ zread_ipv4_route_ipv6_nexthop_add (struct zserv *client, u_short length)
rib->tag = 0; rib->tag = 0;
/* Table */ /* 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); ret = rib_add_ipv6_multipath ((struct prefix *)&p, rib, safi, ifindex);
/* Stats */ /* Stats */
if (ret > 0) if (ret > 0)
@ -1489,9 +1568,20 @@ zread_ipv6_add (struct zserv *client, u_short length, vrf_id_t vrf_id)
else else
rib->tag = 0; rib->tag = 0;
/* Table */
rib->table=zebrad.rtm_table_default;
rib->vrf_id = vrf_id; 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); ret = rib_add_ipv6_multipath ((struct prefix *)&p, rib, safi, ifindex);
/* Stats */ /* Stats */
if (ret > 0) if (ret > 0)
@ -1736,6 +1826,8 @@ zebra_client_create (int sock)
/* Make new read thread. */ /* Make new read thread. */
zebra_event (ZEBRA_READ, sock, client); zebra_event (ZEBRA_READ, sock, client);
zebra_vrf_update_all (client);
} }
/* Handler of zebra service request. */ /* Handler of zebra service request. */
@ -1870,7 +1962,7 @@ zebra_client_read (struct thread *thread)
break; break;
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
case ZEBRA_IPV4_ROUTE_IPV6_NEXTHOP_ADD: 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; break;
case ZEBRA_IPV6_ROUTE_ADD: case ZEBRA_IPV6_ROUTE_ADD:
zread_ipv6_add (client, length, vrf_id); 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); zserv_rnh_register(client, sock, length, RNH_NEXTHOP_TYPE, vrf_id);
break; break;
case ZEBRA_NEXTHOP_UNREGISTER: 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; break;
case ZEBRA_IMPORT_ROUTE_REGISTER: case ZEBRA_IMPORT_ROUTE_REGISTER:
zserv_rnh_register(client, sock, length, RNH_IMPORT_CHECK_TYPE, vrf_id); zserv_rnh_register(client, sock, length, RNH_IMPORT_CHECK_TYPE, vrf_id);
break; break;
case ZEBRA_IMPORT_ROUTE_UNREGISTER: 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; break;
case ZEBRA_BFD_DEST_UPDATE: case ZEBRA_BFD_DEST_UPDATE:
case ZEBRA_BFD_DEST_REGISTER: case ZEBRA_BFD_DEST_REGISTER:

View File

@ -100,6 +100,8 @@ struct zserv
u_int32_t bfd_peer_upd8_cnt; u_int32_t bfd_peer_upd8_cnt;
u_int32_t bfd_peer_del_cnt; u_int32_t bfd_peer_del_cnt;
u_int32_t bfd_peer_replay_cnt; u_int32_t bfd_peer_replay_cnt;
u_int32_t vrfadd_cnt;
u_int32_t vrfdel_cnt;
time_t connect_time; time_t connect_time;
time_t last_read_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 zebra_zserv_socket_init (char *path);
extern void hostinfo_get (void); extern void hostinfo_get (void);
extern void rib_init (void); extern void rib_init (void);
extern void interface_list (struct zebra_vrf *); extern void interface_list (struct zebra_ns *);
extern void route_read (struct zebra_vrf *); extern void route_read (struct zebra_ns *);
extern void kernel_init (struct zebra_vrf *); extern void kernel_init (struct zebra_ns *);
extern void kernel_terminate (struct zebra_vrf *); extern void kernel_terminate (struct zebra_ns *);
extern void zebra_route_map_init (void); extern void zebra_route_map_init (void);
extern void zebra_snmp_init (void); extern void zebra_snmp_init (void);
extern void zebra_vty_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_add (struct zserv *, struct interface *);
extern int zsend_interface_delete (struct zserv *, struct interface *); extern int zsend_interface_delete (struct zserv *, struct interface *);
extern int zsend_interface_address (int, struct zserv *, struct interface *, extern int zsend_interface_address (int, struct zserv *, struct interface *,