summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/vrf.c222
-rwxr-xr-xtools/quagga-reload.py112
-rw-r--r--zebra/zebra_vrf.c3
3 files changed, 244 insertions, 93 deletions
diff --git a/lib/vrf.c b/lib/vrf.c
index dd015e0413..b85ce63f9b 100644
--- a/lib/vrf.c
+++ b/lib/vrf.c
@@ -80,94 +80,182 @@ vrf_build_key (vrf_id_t vrf_id, struct prefix *p)
}
/* Get a VRF. If not found, create one.
- * Arg: name
+ * Arg:
+ * name - The name of the vrf. May be NULL if unknown.
+ * vrf_id - The vrf_id of the vrf. May be VRF_UNKNOWN if unknown
* Description: Please note that this routine can be called with just the name
- and 0 vrf-id */
+ * and 0 vrf-id
+ */
struct vrf *
vrf_get (vrf_id_t vrf_id, const char *name)
{
struct prefix p;
struct route_node *rn = NULL;
struct vrf *vrf = NULL;
- size_t namelen = 0;
-
- /* Only create a route node if the vrf was learned from the kernel */
- if (vrf_id != VRF_UNKNOWN)
- {
- vrf_build_key (vrf_id, &p);
- rn = route_node_get (vrf_table, &p);
-
- if (rn->info)
- {
- vrf = (struct vrf *)rn->info;
- route_unlock_node (rn); /* get */
-
- if (name)
- {
- strncpy (vrf->name, name, strlen(name));
- vrf->name[strlen(name)] = '\0';
- if (vrf_list_lookup_by_name (vrf->name) == NULL)
- listnode_add_sort (vrf_list, vrf);
- }
- if (debug_vrf)
- zlog_debug ("VRF(%u) %s Found %p", vrf_id, (name) ? name : "(NULL)",
- vrf);
- }
- }
-
- if (name && !vrf)
- vrf = vrf_list_lookup_by_name(name);
- if (vrf)
- {
- if (debug_vrf)
- zlog_debug ("VRF(%u) %s lookup by name is successful",
- vrf_id, (name) ? name : "(NULL)");
- }
- else
+ if (debug_vrf)
+ zlog_debug ("VRF_GET: %s(%d)", name, vrf_id);
+
+ /*
+ * Nothing to see, move along here
+ */
+ if (!name && vrf_id == VRF_UNKNOWN)
+ return NULL;
+
+ /*
+ * Valid vrf name and unknown vrf_id case
+ *
+ * This is called when we are configured from
+ * the cli but we have no kernel information yet.
+ */
+ if (name && vrf_id == VRF_UNKNOWN)
{
- if (name)
- {
- namelen = strlen (name);
- if (namelen > VRF_NAMSIZ)
- {
- zlog_err("Attempt to get/create VRF %u name %s - name too long",
- vrf_id, name);
- return NULL;
- }
- }
+ vrf = vrf_list_lookup_by_name (name);
+ if (vrf)
+ return vrf;
vrf = XCALLOC (MTYPE_VRF, sizeof (struct vrf));
if (debug_vrf)
zlog_debug ("VRF(%u) %s is created.",
vrf_id, (name) ? name : "(NULL)");
- if (name)
- {
- strncpy (vrf->name, name, namelen);
- vrf->name[namelen] = '\0';
- listnode_add_sort (vrf_list, vrf);
- }
-
- if ((vrf_id != VRF_UNKNOWN) && (rn != NULL))
- {
- rn->info = vrf;
- vrf->node = rn;
- }
- vrf->vrf_id = vrf_id;
-
- /* Initialize interfaces. */
+ strcpy (vrf->name, name);
+ listnode_add_sort (vrf_list, vrf);
if_init (&vrf->iflist);
+ if (vrf_master.vrf_new_hook)
+ {
+ (*vrf_master.vrf_new_hook) (vrf_id, name, &vrf->info);
+
+ if (debug_vrf && vrf->info)
+ zlog_info ("zvrf is created.");
+ }
+ if (debug_vrf)
+ zlog_debug("Vrf Created: %p", vrf);
+ return vrf;
}
+ /*
+ * Valid vrf name and valid vrf_id case
+ *
+ * This can be passed from the kernel
+ */
+ else if (name && vrf_id != VRF_UNKNOWN)
+ {
+ vrf = vrf_list_lookup_by_name (name);
+ if (vrf)
+ {
+ /*
+ * If the passed in vrf_id and name match
+ * return, nothing to do here.
+ */
+ if (vrf->vrf_id == vrf_id)
+ return vrf;
+
+ /*
+ * Now we have a situation where we've had a
+ * vrf created, but not yet created the vrf_id route
+ * node, let's do so and match the code up.
+ */
+ vrf_build_key (vrf_id, &p);
+ rn = route_node_get (vrf_table, &p);
+
+ rn->info = vrf;
+ vrf->node = rn;
+ vrf->vrf_id = vrf_id;
+ if (vrf_master.vrf_new_hook)
+ (*vrf_master.vrf_new_hook) (vrf_id, name, &vrf->info);
- if (vrf_master.vrf_new_hook && name)
+ if (debug_vrf)
+ zlog_debug("Vrf found matched stuff up: %p", vrf);
+
+ return vrf;
+ }
+ else
+ {
+ /*
+ * We can have 1 of two situations here
+ * We've already been told about the vrf_id
+ * or we haven't.
+ */
+ vrf_build_key (vrf_id, &p);
+ rn = route_node_get (vrf_table, &p);
+ if (rn->info)
+ {
+ vrf = rn->info;
+ route_unlock_node (rn);
+ /*
+ * We know at this point that the vrf->name is not
+ * right because we would have caught it above.
+ * so let's set it.
+ */
+ strcpy (vrf->name, name);
+ listnode_add_sort (vrf_list, vrf);
+ if (vrf_master.vrf_new_hook)
+ {
+ (*vrf_master.vrf_new_hook) (vrf_id, name, &vrf->info);
+
+ if (debug_vrf && vrf->info)
+ zlog_info ("zvrf is created.");
+ }
+ if (debug_vrf)
+ zlog_debug("Vrf Created: %p", vrf);
+ return vrf;
+ }
+ else
+ {
+ vrf = XCALLOC (MTYPE_VRF, sizeof (struct vrf));
+
+ rn->info = vrf;
+ vrf->node = rn;
+ vrf->vrf_id = vrf_id;
+ strcpy (vrf->name, name);
+ listnode_add_sort (vrf_list, vrf);
+ if_init (&vrf->iflist);
+ if (vrf_master.vrf_new_hook)
+ {
+ (*vrf_master.vrf_new_hook) (vrf_id, name, &vrf->info);
+
+ if (debug_vrf && vrf->info)
+ zlog_info ("zvrf is created.");
+ }
+ if (debug_vrf)
+ zlog_debug("Vrf Created: %p", vrf);
+ return vrf;
+ }
+ }
+ }
+ /*
+ * The final case, we've been passed a valid vrf_id
+ * but no name. So we create the route node
+ * if it hasn't already been created.
+ */
+ else if (!name)
{
- (*vrf_master.vrf_new_hook) (vrf_id, name, &vrf->info);
+ vrf_build_key (vrf_id, &p);
+ rn = route_node_get (vrf_table, &p);
+ zlog_debug("Vrf found: %p", rn->info);
- if (vrf->info)
- zlog_info ("zvrf is created.");
+ if (rn->info)
+ {
+ route_unlock_node (rn);
+ return (rn->info);
+ }
+ else
+ {
+ vrf = XCALLOC (MTYPE_VRF, sizeof (struct vrf));
+ rn->info = vrf;
+ vrf->node = rn;
+ vrf->vrf_id = vrf_id;
+ if_init (&vrf->iflist);
+ if (debug_vrf)
+ zlog_debug("Vrf Created: %p", vrf);
+ return vrf;
+ }
}
- return vrf;
+ /*
+ * We shouldn't get here and if we do
+ * something has gone wrong.
+ */
+ return NULL;
}
/* Delete a VRF. This is called in vrf_terminate(). */
diff --git a/tools/quagga-reload.py b/tools/quagga-reload.py
index f67a6ce94a..45f579c4e3 100755
--- a/tools/quagga-reload.py
+++ b/tools/quagga-reload.py
@@ -439,47 +439,107 @@ def line_exist(lines, target_ctx_keys, target_line):
return False
-def ignore_bgp_swpx_peergroup(lines_to_add, lines_to_del):
- '''
- BGP changed how it displays swpX peers that are part of peer-group. Older
- versions of quagga would display these on separate lines:
- neighbor swp1 interface
- neighbor swp1 peer-group FOO
-
- but today we display via a single line
- neighbor swp1 interface peer-group FOO
-
- This change confuses quagga-reload.py so check to see if we are deleting
- neighbor swp1 interface peer-group FOO
-
- and adding
- neighbor swp1 interface
- neighbor swp1 peer-group FOO
-
- If so then chop the del line and the corresponding add lines
- '''
+def ignore_delete_re_add_lines(lines_to_add, lines_to_del):
# Quite possibly the most confusing (while accurate) variable names in history
lines_to_add_to_del = []
lines_to_del_to_del = []
for (ctx_keys, line) in lines_to_del:
+ deleted = False
+
if ctx_keys[0].startswith('router bgp') and line.startswith('neighbor '):
+ """
+ BGP changed how it displays swpX peers that are part of peer-group. Older
+ versions of quagga would display these on separate lines:
+ neighbor swp1 interface
+ neighbor swp1 peer-group FOO
+
+ but today we display via a single line
+ neighbor swp1 interface peer-group FOO
+
+ This change confuses quagga-reload.py so check to see if we are deleting
+ neighbor swp1 interface peer-group FOO
+
+ and adding
+ neighbor swp1 interface
+ neighbor swp1 peer-group FOO
+
+ If so then chop the del line and the corresponding add lines
+ """
+
re_swpx_int_peergroup = re.search('neighbor (\S+) interface peer-group (\S+)', line)
+ re_swpx_int_v6only_peergroup = re.search('neighbor (\S+) interface v6only peer-group (\S+)', line)
- if re_swpx_int_peergroup:
- swpx = re_swpx_int_peergroup.group(1)
- peergroup = re_swpx_int_peergroup.group(2)
- swpx_interface = "neighbor %s interface" % swpx
- swpx_peergroup = "neighbor %s peer-group %s" % (swpx, peergroup)
+ if re_swpx_int_peergroup or re_swpx_int_v6only_peergroup:
+ swpx_interface = None
+ swpx_peergroup = None
+
+ if re_swpx_int_peergroup:
+ swpx = re_swpx_int_peergroup.group(1)
+ peergroup = re_swpx_int_peergroup.group(2)
+ swpx_interface = "neighbor %s interface" % swpx
+ elif re_swpx_int_v6only_peergroup:
+ swpx = re_swpx_int_v6only_peergroup.group(1)
+ peergroup = re_swpx_int_v6only_peergroup.group(2)
+ swpx_interface = "neighbor %s interface v6only" % swpx
+ swpx_peergroup = "neighbor %s peer-group %s" % (swpx, peergroup)
found_add_swpx_interface = line_exist(lines_to_add, ctx_keys, swpx_interface)
found_add_swpx_peergroup = line_exist(lines_to_add, ctx_keys, swpx_peergroup)
+ tmp_ctx_keys = list(ctx_keys)
+
+ if not found_add_swpx_peergroup:
+ tmp_ctx_keys = list(ctx_keys)
+ tmp_ctx_keys.append('address-family ipv4 unicast')
+ tmp_ctx_keys = tuple(tmp_ctx_keys)
+ found_add_swpx_peergroup = line_exist(lines_to_add, tmp_ctx_keys, swpx_peergroup)
+
+ if not found_add_swpx_peergroup:
+ tmp_ctx_keys = list(ctx_keys)
+ tmp_ctx_keys.append('address-family ipv6 unicast')
+ tmp_ctx_keys = tuple(tmp_ctx_keys)
+ found_add_swpx_peergroup = line_exist(lines_to_add, tmp_ctx_keys, swpx_peergroup)
if found_add_swpx_interface and found_add_swpx_peergroup:
+ deleted = True
lines_to_del_to_del.append((ctx_keys, line))
lines_to_add_to_del.append((ctx_keys, swpx_interface))
- lines_to_add_to_del.append((ctx_keys, swpx_peergroup))
+ lines_to_add_to_del.append((tmp_ctx_keys, swpx_peergroup))
+
+ if not deleted:
+ found_add_line = line_exist(lines_to_add, ctx_keys, line)
+
+ if found_add_line:
+ lines_to_del_to_del.append((ctx_keys, line))
+ lines_to_add_to_del.append((ctx_keys, line))
+ else:
+ '''
+ We have commands that used to be displayed in the global part
+ of 'router bgp' that are now displayed under 'address-family ipv4 unicast'
+
+ # old way
+ router bgp 64900
+ neighbor ISL advertisement-interval 0
+
+ vs.
+
+ # new way
+ router bgp 64900
+ address-family ipv4 unicast
+ neighbor ISL advertisement-interval 0
+
+ Look to see if we are deleting it in one format just to add it back in the other
+ '''
+ if ctx_keys[0].startswith('router bgp') and len(ctx_keys) > 1 and ctx_keys[1] == 'address-family ipv4 unicast':
+ tmp_ctx_keys = list(ctx_keys)[:-1]
+ tmp_ctx_keys = tuple(tmp_ctx_keys)
+
+ found_add_line = line_exist(lines_to_add, tmp_ctx_keys, line)
+
+ if found_add_line:
+ lines_to_del_to_del.append((ctx_keys, line))
+ lines_to_add_to_del.append((tmp_ctx_keys, line))
for (ctx_keys, line) in lines_to_del_to_del:
lines_to_del.remove((ctx_keys, line))
@@ -548,7 +608,7 @@ def compare_context_objects(newconf, running):
for line in newconf_ctx.lines:
lines_to_add.append((newconf_ctx_keys, line))
- (lines_to_add, lines_to_del) = ignore_bgp_swpx_peergroup(lines_to_add, lines_to_del)
+ (lines_to_add, lines_to_del) = ignore_delete_re_add_lines(lines_to_add, lines_to_del)
return (lines_to_add, lines_to_del, restart_bgpd)
diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c
index 5624435f88..0eba902112 100644
--- a/zebra/zebra_vrf.c
+++ b/zebra/zebra_vrf.c
@@ -88,6 +88,9 @@ zebra_vrf_new (vrf_id_t vrf_id, const char *name, void **info)
router_id_init (zvrf);
}
+ if (zvrf->vrf_id == VRF_UNKNOWN)
+ zvrf->vrf_id = vrf_id;
+
return 0;
}