mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-05-11 19:05:25 +00:00
Merge branch 'cmaster' of ssh://stash.cumulusnetworks.com:7999/quag/quagga into cmaster
This commit is contained in:
commit
f47603b04d
224
lib/vrf.c
224
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.
|
/* 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
|
* Description: Please note that this routine can be called with just the name
|
||||||
and 0 vrf-id */
|
* and 0 vrf-id
|
||||||
|
*/
|
||||||
struct vrf *
|
struct vrf *
|
||||||
vrf_get (vrf_id_t vrf_id, const char *name)
|
vrf_get (vrf_id_t vrf_id, const char *name)
|
||||||
{
|
{
|
||||||
struct prefix p;
|
struct prefix p;
|
||||||
struct route_node *rn = NULL;
|
struct route_node *rn = NULL;
|
||||||
struct vrf *vrf = NULL;
|
struct vrf *vrf = NULL;
|
||||||
size_t namelen = 0;
|
|
||||||
|
|
||||||
/* Only create a route node if the vrf was learned from the kernel */
|
if (debug_vrf)
|
||||||
if (vrf_id != VRF_UNKNOWN)
|
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)
|
||||||
{
|
{
|
||||||
vrf_build_key (vrf_id, &p);
|
vrf = vrf_list_lookup_by_name (name);
|
||||||
rn = route_node_get (vrf_table, &p);
|
if (vrf)
|
||||||
|
return vrf;
|
||||||
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 (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 = XCALLOC (MTYPE_VRF, sizeof (struct vrf));
|
vrf = XCALLOC (MTYPE_VRF, sizeof (struct vrf));
|
||||||
if (debug_vrf)
|
if (debug_vrf)
|
||||||
zlog_debug ("VRF(%u) %s is created.",
|
zlog_debug ("VRF(%u) %s is created.",
|
||||||
vrf_id, (name) ? name : "(NULL)");
|
vrf_id, (name) ? name : "(NULL)");
|
||||||
if (name)
|
strcpy (vrf->name, name);
|
||||||
{
|
listnode_add_sort (vrf_list, vrf);
|
||||||
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. */
|
|
||||||
if_init (&vrf->iflist);
|
if_init (&vrf->iflist);
|
||||||
}
|
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 && 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_master.vrf_new_hook) (vrf_id, name, &vrf->info);
|
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;
|
||||||
|
|
||||||
if (vrf->info)
|
/*
|
||||||
zlog_info ("zvrf is created.");
|
* 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 (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_build_key (vrf_id, &p);
|
||||||
|
rn = route_node_get (vrf_table, &p);
|
||||||
|
zlog_debug("Vrf found: %p", rn->info);
|
||||||
|
|
||||||
|
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(). */
|
/* Delete a VRF. This is called in vrf_terminate(). */
|
||||||
|
@ -439,47 +439,107 @@ def line_exist(lines, target_ctx_keys, target_line):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def ignore_bgp_swpx_peergroup(lines_to_add, lines_to_del):
|
def ignore_delete_re_add_lines(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
|
|
||||||
'''
|
|
||||||
|
|
||||||
# Quite possibly the most confusing (while accurate) variable names in history
|
# Quite possibly the most confusing (while accurate) variable names in history
|
||||||
lines_to_add_to_del = []
|
lines_to_add_to_del = []
|
||||||
lines_to_del_to_del = []
|
lines_to_del_to_del = []
|
||||||
|
|
||||||
for (ctx_keys, line) in lines_to_del:
|
for (ctx_keys, line) in lines_to_del:
|
||||||
|
deleted = False
|
||||||
|
|
||||||
if ctx_keys[0].startswith('router bgp') and line.startswith('neighbor '):
|
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_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 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
|
||||||
|
|
||||||
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)
|
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_interface = line_exist(lines_to_add, ctx_keys, swpx_interface)
|
||||||
found_add_swpx_peergroup = line_exist(lines_to_add, ctx_keys, swpx_peergroup)
|
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:
|
if found_add_swpx_interface and found_add_swpx_peergroup:
|
||||||
|
deleted = True
|
||||||
lines_to_del_to_del.append((ctx_keys, line))
|
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_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:
|
for (ctx_keys, line) in lines_to_del_to_del:
|
||||||
lines_to_del.remove((ctx_keys, line))
|
lines_to_del.remove((ctx_keys, line))
|
||||||
@ -548,7 +608,7 @@ def compare_context_objects(newconf, running):
|
|||||||
for line in newconf_ctx.lines:
|
for line in newconf_ctx.lines:
|
||||||
lines_to_add.append((newconf_ctx_keys, line))
|
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)
|
return (lines_to_add, lines_to_del, restart_bgpd)
|
||||||
|
|
||||||
|
@ -88,6 +88,9 @@ zebra_vrf_new (vrf_id_t vrf_id, const char *name, void **info)
|
|||||||
router_id_init (zvrf);
|
router_id_init (zvrf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (zvrf->vrf_id == VRF_UNKNOWN)
|
||||||
|
zvrf->vrf_id = vrf_id;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user