Merge pull request #12494 from louis-6wind/ext_admin_group

lib,zebra,isisd: add support for extended admin group RFC7308
This commit is contained in:
Olivier Dugeon 2023-02-15 09:42:03 +01:00 committed by GitHub
commit e2b958ecbc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
45 changed files with 5181 additions and 64 deletions

32
doc/user/affinitymap.rst Normal file
View File

@ -0,0 +1,32 @@
.. _affinity-map:
*************
Affinity Maps
*************
Affinity maps provide a means of configuring Standard Admininistrative-Group
(RFC3630, RFC5305 and RFC5329) and Extended Admininistrative-Group (RFC7308).
An affinity-map maps a specific bit position to a human readable-name.
An affinity refers to a color or a ressource class in the Traffic Engineering
terminology. The bit position means the position of the bit set starting from
the least significant bit. For example, if the affinity 'blue' has bit position
0 the extended Admin-Group value will be 0x01. If the affinity 'red' bit
position 2 was added to a link in combination with the 'blue' affinity, the
Admin-Group value would be 0x05.
Command
-------
.. clicmd:: affinity-map NAME bit-position (0-1023)
Map the affinity name NAME to the bit-position. The bit-position is the key
so that only one name can be mapped to particular bit-position.
.. clicmd:: no affinity-map NAME
Remove the affinity-map mapping.
Affinity-maps with a bit-position value higher than 31 are not compatible with
Standard Admininistrative-Group. The CLI disallow the usage of such
affinity-maps when Standard Admininistrative-Groups are required.

View File

@ -3,6 +3,7 @@
#
user_RSTFILES = \
doc/user/affinitymap.rst \
doc/user/babeld.rst \
doc/user/ldpd.rst \
doc/user/basic.rst \

View File

@ -222,8 +222,6 @@ Link Parameters Commands
.. clicmd:: unrsv-bw (0-7) BANDWIDTH
.. clicmd:: admin-grp BANDWIDTH
These commands specifies the Traffic Engineering parameters of the interface
in conformity to RFC3630 (OSPF) or RFC5305 (ISIS). There are respectively
the TE Metric (different from the OSPF or ISIS metric), Maximum Bandwidth
@ -234,6 +232,36 @@ Link Parameters Commands
Note that BANDWIDTH is specified in IEEE floating point format and express
in Bytes/second.
.. clicmd:: admin-grp 0x(0-FFFFFFFF)
This commands configures the Traffic Engineering Admin-Group of the interface
as specified in RFC3630 (OSPF) or RFC5305 (ISIS). Admin-group is also known
as Resource Class/Color in the OSPF protocol.
.. clicmd:: [no] affinity AFFINITY-MAP-NAME
This commands configures the Traffic Engineering Admin-Group of the
interface using the affinity-map definitions (:ref:`affinity-map`).
Multiple AFFINITY-MAP-NAME can be specified at the same time. Affinity-map
names are added or removed if ``no`` is present. It means that specifying one
value does not override the full list.
``admin-grp`` and ``affinity`` commands provide two ways of setting
admin-groups. They cannot be both set on the same interface.
.. clicmd:: [no] affinity-mode [extended|standard|both]
This commands configures which admin-group format is set by the affinity
command. ``extended`` Admin-Group is the default and uses the RFC7308 format.
``standard`` mode uses the standard admin-group format that is defined by
RFC3630, RFC5305 and RFC5329. When the ``standard`` mode is set,
affinity-maps with bit-positions higher than 31 cannot be applied to the
interface. The ``both`` mode allows setting standard and extended admin-group
on the link at the same time. In this case, the bit-positions 0 to 31 are
the same on standard and extended admin-groups.
Note that extended admin-groups are only supported by IS-IS for the moment.
.. clicmd:: delay (0-16777215) [min (0-16777215) | max (0-16777215)]
.. clicmd:: delay-variation (0-16777215)

View File

@ -40,6 +40,7 @@
#include "qobj.h"
#include "libfrr.h"
#include "routemap.h"
#include "affinitymap.h"
#include "isisd/isis_constants.h"
#include "isisd/isis_common.h"
@ -167,6 +168,7 @@ struct frr_signal_t isisd_signals[] = {
};
/* clang-format off */
static const struct frr_yang_module_info *const isisd_yang_modules[] = {
&frr_filter_info,
&frr_interface_info,
@ -174,8 +176,10 @@ static const struct frr_yang_module_info *const isisd_yang_modules[] = {
&frr_isisd_info,
#endif /* ifndef FABRICD */
&frr_route_map_info,
&frr_affinity_map_info,
&frr_vrf_info,
};
/* clang-format on */
#ifdef FABRICD
FRR_DAEMON_INFO(fabricd, OPEN_FABRIC, .vty_port = FABRICD_VTY_PORT,
@ -264,6 +268,8 @@ int main(int argc, char **argv, char **envp)
lsp_init();
mt_init();
affinity_map_init();
isis_zebra_init(master, instance);
isis_bfd_init(master);
isis_ldp_sync_init();

View File

@ -218,6 +218,13 @@ void isis_link_params_update(struct isis_circuit *circuit,
} else
UNSET_SUBTLV(ext, EXT_ADM_GRP);
if (IS_PARAM_SET(ifp->link_params, LP_EXTEND_ADM_GRP)) {
admin_group_copy(&ext->ext_admin_group,
&ifp->link_params->ext_admin_grp);
SET_SUBTLV(ext, EXT_EXTEND_ADM_GRP);
} else
UNSET_SUBTLV(ext, EXT_EXTEND_ADM_GRP);
/* If known, register local IPv4 addr from ip_addr list */
if (listcount(circuit->ip_addrs) != 0) {
addr = (struct prefix_ipv4 *)listgetdata(
@ -758,6 +765,11 @@ static struct ls_attributes *get_attributes(struct ls_node_id adv,
attr->standard.admin_group = tlvs->adm_group;
SET_FLAG(attr->flags, LS_ATTR_ADM_GRP);
}
if (CHECK_FLAG(tlvs->status, EXT_EXTEND_ADM_GRP)) {
admin_group_copy(&attr->ext_admin_group,
&tlvs->ext_admin_group);
SET_FLAG(attr->flags, LS_ATTR_EXT_ADM_GRP);
}
if (CHECK_FLAG(tlvs->status, EXT_LLRI)) {
attr->standard.local_id = tlvs->local_llri;
attr->standard.remote_id = tlvs->remote_llri;

View File

@ -136,6 +136,8 @@ struct isis_ext_subtlvs *isis_alloc_ext_subtlvs(void)
init_item_list(&ext->adj_sid);
init_item_list(&ext->lan_sid);
admin_group_init(&ext->ext_admin_group);
return ext;
}
@ -155,6 +157,9 @@ void isis_del_ext_subtlvs(struct isis_ext_subtlvs *ext)
next_item = item->next;
XFREE(MTYPE_ISIS_SUBTLV, item);
}
admin_group_term(&ext->ext_admin_group);
XFREE(MTYPE_ISIS_SUBTLV, ext);
}
@ -233,6 +238,9 @@ copy_item_ext_subtlvs(struct isis_ext_subtlvs *exts, uint16_t mtid)
SET_SUBTLV(rv, EXT_LAN_ADJ_SID);
}
rv->ext_admin_group.bitmap.data = NULL;
admin_group_copy(&rv->ext_admin_group, &exts->ext_admin_group);
return rv;
}
@ -241,6 +249,7 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
struct sbuf *buf, struct json_object *json,
int indent, uint16_t mtid)
{
char admin_group_buf[ADMIN_GROUP_PRINT_MAX_SIZE];
char aux_buf[255];
char cnt_buf[255];
@ -250,9 +259,37 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
snprintfrr(aux_buf, sizeof(aux_buf), "0x%x",
exts->adm_group);
json_object_string_add(json, "adm-group", aux_buf);
} else
} else {
sbuf_push(buf, indent, "Administrative Group: 0x%x\n",
exts->adm_group);
sbuf_push(buf, indent + 2, "Bit positions: %s\n",
admin_group_standard_print(
admin_group_buf,
indent + strlen("Admin Group: "),
exts->adm_group));
}
}
if (IS_SUBTLV(exts, EXT_EXTEND_ADM_GRP) &&
admin_group_nb_words(&exts->ext_admin_group) != 0) {
if (!json) {
/* TODO json after fix show database detail json */
sbuf_push(buf, indent, "Ext Admin Group: %s\n",
admin_group_string(
admin_group_buf,
ADMIN_GROUP_PRINT_MAX_SIZE,
indent + strlen("Ext Admin Group: "),
&exts->ext_admin_group));
admin_group_print(admin_group_buf,
indent + strlen("Ext Admin Group: "),
&exts->ext_admin_group);
if (admin_group_buf[0] != '\0' &&
(buf->pos + strlen(admin_group_buf) +
SBUF_DEFAULT_SIZE / 2) < buf->size)
sbuf_push(buf, indent + 2,
"Bit positions: %s\n",
admin_group_buf);
}
}
if (IS_SUBTLV(exts, EXT_LLRI)) {
if (json) {
@ -685,6 +722,24 @@ static int pack_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
stream_putc(s, ISIS_SUBTLV_DEF_SIZE);
stream_putl(s, exts->adm_group);
}
if (IS_SUBTLV(exts, EXT_EXTEND_ADM_GRP) &&
admin_group_nb_words(&exts->ext_admin_group) != 0) {
/* Extended Administrative Group */
size_t ag_length;
size_t ag_length_pos;
struct admin_group *ag;
stream_putc(s, ISIS_SUBTLV_EXT_ADMIN_GRP);
ag_length_pos = stream_get_endp(s);
stream_putc(s, 0); /* length will be filled later*/
ag = &exts->ext_admin_group;
for (size_t i = 0; i < admin_group_nb_words(ag); i++)
stream_putl(s, ag->bitmap.data[i]);
ag_length = stream_get_endp(s) - ag_length_pos - 1;
stream_putc_at(s, ag_length_pos, ag_length);
}
if (IS_SUBTLV(exts, EXT_LLRI)) {
stream_putc(s, ISIS_SUBTLV_LLRI);
stream_putc(s, ISIS_SUBTLV_LLRI_SIZE);
@ -828,6 +883,8 @@ static int unpack_item_ext_subtlvs(uint16_t mtid, uint8_t len, struct stream *s,
uint8_t sum = 0;
uint8_t subtlv_type;
uint8_t subtlv_len;
size_t nb_groups;
uint32_t val;
struct isis_extended_reach *rv = dest;
struct isis_ext_subtlvs *exts = isis_alloc_ext_subtlvs();
@ -863,6 +920,15 @@ static int unpack_item_ext_subtlvs(uint16_t mtid, uint8_t len, struct stream *s,
SET_SUBTLV(exts, EXT_ADM_GRP);
}
break;
case ISIS_SUBTLV_EXT_ADMIN_GRP:
nb_groups = subtlv_len / sizeof(uint32_t);
for (size_t i = 0; i < nb_groups; i++) {
val = stream_getl(s);
admin_group_bulk_set(&exts->ext_admin_group,
val, i);
}
SET_SUBTLV(exts, EXT_EXTEND_ADM_GRP);
break;
case ISIS_SUBTLV_LLRI:
if (subtlv_len != ISIS_SUBTLV_LLRI_SIZE) {
sbuf_push(log, indent,

View File

@ -441,6 +441,9 @@ enum ext_subtlv_size {
ISIS_SUBTLV_HDR_SIZE = 2,
ISIS_SUBTLV_DEF_SIZE = 4,
/* RFC 7308 */
ISIS_SUBTLV_EXT_ADMIN_GRP = 14,
ISIS_SUBTLV_MAX_SIZE = 180
};
@ -471,6 +474,7 @@ enum ext_subtlv_size {
#define EXT_RES_BW 0x040000
#define EXT_AVA_BW 0x080000
#define EXT_USE_BW 0x100000
#define EXT_EXTEND_ADM_GRP 0x200000
/*
* This structure groups all Extended IS Reachability subTLVs.
@ -491,6 +495,7 @@ struct isis_ext_subtlvs {
uint32_t status;
uint32_t adm_group; /* Resource Class/Color - RFC 5305 */
struct admin_group ext_admin_group; /* Res. Class/Color - RFC 7308 */
/* Link Local/Remote Identifiers - RFC 5307 */
uint32_t local_llri;
uint32_t remote_llri;

402
lib/admin_group.c Normal file
View File

@ -0,0 +1,402 @@
/*
* Administrative-group library (RFC3630, RFC5305, RFC5329, RFC7308)
*
* Copyright 2022 Hiroki Shirokura, LINE Corporation
* Copyright 2022 Masakazu Asama
* Copyright 2022 6WIND S.A.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; see the file COPYING; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "admin_group.h"
#include "bitfield.h"
char *admin_group_string(char *out, size_t sz, int indent,
const struct admin_group *ag)
{
bool printed = false;
size_t index = 2;
int nb_print = 0;
if (sz < index)
return out;
if (admin_group_explicit_zero(ag)) {
snprintf(out, sz, "0x00000000");
return out;
}
if (admin_group_zero(ag)) {
snprintf(out, sz, "not-set");
return out;
}
snprintf(out, sz, "0x");
for (ssize_t i = ag->bitmap.m - 1; i >= 0; i--) {
if (sz - index <= 0)
break;
if (ag->bitmap.data[i] == 0 && !printed)
continue;
if (nb_print != 0 && (nb_print % 4) == 0) {
snprintf(&out[index], sz - index, "\n%*s", indent, "");
index += indent + 1;
snprintf(&out[index], sz - index, "0x%08x ",
ag->bitmap.data[i]);
index += 2;
} else
snprintf(&out[index], sz - index, "%08x ",
ag->bitmap.data[i]);
index += 9;
nb_print++;
printed = true;
}
return out;
}
char *admin_group_standard_print(char *out, int indent, uint32_t bitmap)
{
bool first = true;
int bit, i;
size_t ret, line_sz = 0, line_max_sz;
out[0] = '\0';
if (bitmap == 0) {
snprintf(out, ADMIN_GROUP_PRINT_MAX_SIZE, "not-set");
return out;
}
line_max_sz = strlen("0xffffffff ffffffff ffffffff ffffffff");
for (i = 0; i < 32; i++) {
bit = bitmap >> i & 1;
if (bit == 0)
continue;
if (!first) {
ret = snprintf(&out[strlen(out)],
ADMIN_GROUP_PRINT_MAX_SIZE - strlen(out),
", ");
line_sz += ret;
}
if (line_sz >= line_max_sz) {
snprintf(&out[strlen(out)],
ADMIN_GROUP_PRINT_MAX_SIZE - strlen(out),
"\n%*s", indent, "");
line_sz = 0;
}
ret = snprintf(&out[strlen(out)],
ADMIN_GROUP_PRINT_MAX_SIZE - strlen(out), "%d",
i);
line_sz += ret;
first = false;
}
return out;
}
char *admin_group_print(char *out, int indent, const struct admin_group *ag)
{
bool first = true;
uint32_t i;
size_t ret, line_sz = 0, line_max_sz;
out[0] = '\0';
if (admin_group_size(ag) == 0) {
snprintf(out, ADMIN_GROUP_PRINT_MAX_SIZE, "not-set");
return out;
}
line_max_sz = strlen("0xffffffff ffffffff ffffffff ffffffff");
for (i = 0; i < (admin_group_size(ag) * WORD_SIZE); i++) {
if (!admin_group_get(ag, i))
continue;
if (!first) {
ret = snprintf(&out[strlen(out)],
ADMIN_GROUP_PRINT_MAX_SIZE - strlen(out),
", ");
line_sz += ret;
}
if (line_sz >= line_max_sz) {
snprintf(&out[strlen(out)],
ADMIN_GROUP_PRINT_MAX_SIZE - strlen(out),
"\n%*s", indent, "");
line_sz = 0;
}
ret = snprintf(&out[strlen(out)],
ADMIN_GROUP_PRINT_MAX_SIZE - strlen(out), "%d",
i);
line_sz += ret;
if (ret >= (ADMIN_GROUP_PRINT_MAX_SIZE - strlen(out))) {
out[0] = '\0';
return out;
}
first = false;
}
return out;
}
bool admin_group_cmp(const struct admin_group *ag1,
const struct admin_group *ag2)
{
size_t i;
for (i = 0; i < ag1->bitmap.m || i < ag2->bitmap.m; i++) {
if (i >= ag1->bitmap.m) {
if (ag2->bitmap.data[i] != 0)
return false;
} else if (i >= ag2->bitmap.m) {
if (ag1->bitmap.data[i] != 0)
return false;
} else if (memcmp(&ag1->bitmap.data[i], &ag2->bitmap.data[i],
sizeof(word_t)) != 0)
return false;
}
return true;
}
void admin_group_copy(struct admin_group *dst, const struct admin_group *src)
{
assert(bf_is_inited(src->bitmap));
if (bf_is_inited(dst->bitmap))
bf_free(dst->bitmap);
dst->bitmap = bf_copy(src->bitmap);
}
void admin_group_init(struct admin_group *ag)
{
assert(!bf_is_inited(ag->bitmap));
bf_init(ag->bitmap, WORD_SIZE);
}
void admin_group_term(struct admin_group *ag)
{
assert(bf_is_inited(ag->bitmap));
bf_free(ag->bitmap);
}
word_t admin_group_get_offset(const struct admin_group *ag, size_t oct_offset)
{
assert(bf_is_inited(ag->bitmap));
if (ag->bitmap.m < oct_offset)
return 0;
return ag->bitmap.data[oct_offset];
}
static void admin_group_extend(struct admin_group *ag, size_t idx)
{
size_t old_m, m;
old_m = ag->bitmap.m;
m = idx + 1;
ag->bitmap.m = m;
ag->bitmap.data =
XREALLOC(MTYPE_BITFIELD, ag->bitmap.data, m * sizeof(word_t));
memset(&ag->bitmap.data[old_m], 0, (m - old_m) * sizeof(word_t));
}
void admin_group_set(struct admin_group *ag, size_t pos)
{
size_t idx = bf_index(pos);
if (idx >= ag->bitmap.m)
admin_group_extend(ag, idx);
ag->bitmap.data[idx] |= 1 << (bf_offset(pos));
if (idx >= ag->bitmap.n)
ag->bitmap.n = idx + 1;
}
void admin_group_unset(struct admin_group *ag, size_t pos)
{
if (bf_index(pos) > (ag->bitmap.m - 1))
return;
bf_release_index(ag->bitmap, pos);
ag->bitmap.n = admin_group_size(ag);
}
int admin_group_get(const struct admin_group *ag, size_t pos)
{
size_t admin_group_length = admin_group_size(ag);
uint32_t oct_offset;
size_t idx;
if (admin_group_length == 0)
return 0;
idx = bf_index(pos);
if (idx >= admin_group_length)
return 0;
oct_offset = admin_group_get_offset(ag, idx);
return oct_offset >> pos & 1;
}
void admin_group_bulk_set(struct admin_group *ag, uint32_t bitmap,
size_t oct_offset)
{
if (bitmap == 0 && oct_offset == 0) {
admin_group_allow_explicit_zero(ag);
return;
}
if (oct_offset >= ag->bitmap.m)
admin_group_extend(ag, oct_offset);
ag->bitmap.data[oct_offset] = bitmap;
if (oct_offset >= ag->bitmap.n)
ag->bitmap.n = oct_offset + 1;
}
size_t admin_group_size(const struct admin_group *ag)
{
size_t size = 0;
for (size_t i = 0; i < ag->bitmap.m; i++)
if (ag->bitmap.data[i] != 0)
size = i + 1;
return size;
}
size_t admin_group_nb_words(const struct admin_group *ag)
{
return ag->bitmap.n;
}
void admin_group_clear(struct admin_group *ag)
{
for (size_t i = 0; i < ag->bitmap.m; i++)
ag->bitmap.data[i] = 0;
ag->bitmap.n = 0;
}
bool admin_group_zero(const struct admin_group *ag)
{
for (size_t i = 0; i < ag->bitmap.m; i++)
if (ag->bitmap.data[i] != 0)
return false;
return true;
}
bool admin_group_explicit_zero(const struct admin_group *ag)
{
return ag->bitmap.n == 1 && ag->bitmap.data[0] == 0;
}
void admin_group_allow_explicit_zero(struct admin_group *ag)
{
if (admin_group_zero(ag))
ag->bitmap.n = 1;
}
void admin_group_disallow_explicit_zero(struct admin_group *ag)
{
if (admin_group_zero(ag))
ag->bitmap.n = 0;
}
/* link_std_ag: admin-group in the RFC5305 section 3.1 format
* link_ext_ag: admin-group in the RFC7308 format
* RFC7308 specifies in section 2.3.1 that:
* "If both an AG and EAG are present, a receiving node MUST use the AG
* as the first 32 bits (0-31) of administrative color and use the EAG
* for bits 32 and higher, if present."
*/
bool admin_group_match_any(const struct admin_group *fad_ag,
const uint32_t *link_std_ag,
const struct admin_group *link_ext_ag)
{
size_t fad_ag_sz, link_ag_sz, i;
uint32_t link_ag_bitmap, fad_ag_bitmap;
assert(fad_ag);
/* get the size of admin-groups: i.e. number of used words */
fad_ag_sz = admin_group_size(fad_ag);
if (link_std_ag && link_ext_ag) {
link_ag_sz = admin_group_size(link_ext_ag);
if (link_ag_sz == 0)
link_ag_sz = 1;
} else if (link_std_ag && !link_ext_ag)
link_ag_sz = 1;
else if (!link_std_ag && link_ext_ag)
link_ag_sz = admin_group_size(link_ext_ag);
else
link_ag_sz = 0;
for (i = 0; i < fad_ag_sz && i < link_ag_sz; i++) {
fad_ag_bitmap = fad_ag->bitmap.data[i];
if (i == 0 && link_std_ag)
link_ag_bitmap = *link_std_ag;
else
link_ag_bitmap = link_ext_ag->bitmap.data[i];
if (fad_ag_bitmap & link_ag_bitmap)
return true;
}
return false;
}
/* same comments as admin_group_match_any() */
bool admin_group_match_all(const struct admin_group *fad_ag,
const uint32_t *link_std_ag,
const struct admin_group *link_ext_ag)
{
size_t fad_ag_sz, link_ag_sz, i;
uint32_t link_ag_bitmap, fad_ag_bitmap;
assert(fad_ag);
/* get the size of admin-groups: i.e. number of used words */
fad_ag_sz = admin_group_size(fad_ag);
if (link_std_ag && link_ext_ag) {
link_ag_sz = admin_group_size(link_ext_ag);
if (link_ag_sz == 0)
link_ag_sz = 1;
} else if (link_std_ag && !link_ext_ag)
link_ag_sz = 1;
else if (!link_std_ag && link_ext_ag)
link_ag_sz = admin_group_size(link_ext_ag);
else
link_ag_sz = 0;
if (fad_ag_sz > link_ag_sz)
return false;
for (i = 0; i < fad_ag_sz; i++) {
fad_ag_bitmap = fad_ag->bitmap.data[i];
if (fad_ag_bitmap == 0)
continue;
if (i == 0 && link_std_ag)
link_ag_bitmap = *link_std_ag;
else
link_ag_bitmap = link_ext_ag->bitmap.data[i];
if ((fad_ag_bitmap & link_ag_bitmap) != fad_ag_bitmap)
return false;
}
return true;
}

68
lib/admin_group.h Normal file
View File

@ -0,0 +1,68 @@
/*
* Administrative-group library (RFC3630, RFC5305, RFC5329, RFC7308)
*
* Copyright 2022 Hiroki Shirokura, LINE Corporation
* Copyright 2022 Masakazu Asama
* Copyright 2022 6WIND S.A.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; see the file COPYING; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _FRR_ADMIN_GROUP_H
#define _FRR_ADMIN_GROUP_H
#include "zebra.h"
#include "memory.h"
#include "bitfield.h"
#define ADMIN_GROUP_PRINT_MAX_SIZE 2048
#define EXT_ADMIN_GROUP_MAX_POSITIONS 1024
struct admin_group {
bitfield_t bitmap;
};
char *admin_group_string(char *out, size_t sz, int indent,
const struct admin_group *ag);
char *admin_group_standard_print(char *out, int indent, uint32_t bitmap);
char *admin_group_print(char *out, int indent, const struct admin_group *ag);
bool admin_group_cmp(const struct admin_group *ag1,
const struct admin_group *ag2);
void admin_group_copy(struct admin_group *dst, const struct admin_group *src);
void admin_group_init(struct admin_group *ag);
void admin_group_term(struct admin_group *ag);
uint32_t admin_group_get_offset(const struct admin_group *ag,
size_t oct_offset);
void admin_group_set(struct admin_group *ag, size_t pos);
void admin_group_unset(struct admin_group *ag, size_t pos);
int admin_group_get(const struct admin_group *ag, size_t pos);
void admin_group_bulk_set(struct admin_group *ag, uint32_t bitmap,
size_t oct_offset);
size_t admin_group_size(const struct admin_group *ag);
size_t admin_group_nb_words(const struct admin_group *ag);
void admin_group_clear(struct admin_group *ag);
bool admin_group_zero(const struct admin_group *ag);
bool admin_group_explicit_zero(const struct admin_group *ag);
void admin_group_allow_explicit_zero(struct admin_group *ag);
void admin_group_disallow_explicit_zero(struct admin_group *ag);
bool admin_group_match_any(const struct admin_group *fad_ag,
const uint32_t *link_std_ag,
const struct admin_group *link_ag);
bool admin_group_match_all(const struct admin_group *fad_ag,
const uint32_t *link_std_ag,
const struct admin_group *link_ag);
#endif /* _FRR_ADMIN_GROUP_H */

173
lib/affinitymap.c Normal file
View File

@ -0,0 +1,173 @@
/*
* Affinity map function.
*
* Copyright 2022 Hiroki Shirokura, LINE Corporation
* Copyright 2022 Masakazu Asama
* Copyright 2022 6WIND S.A.
*
* This file is part of Free Range Routing (FRR).
*
* FRR is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* FRR is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; see the file COPYING; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
#include "linklist.h"
#include "memory.h"
#include "command.h"
#include "vector.h"
#include "prefix.h"
#include "vty.h"
#include "affinitymap.h"
#include "command.h"
#include "log.h"
#include "hash.h"
#include "libfrr.h"
#include "lib_errors.h"
#include "table.h"
#include "json.h"
#include "jhash.h"
DEFINE_MTYPE_STATIC(LIB, AFFINITY_MAP, "Affinity map");
DEFINE_MTYPE(LIB, AFFINITY_MAP_NAME, "Affinity map name");
DEFINE_MTYPE_STATIC(LIB, AFFINITY_MAP_INDEX, "Affinity map index");
DEFINE_QOBJ_TYPE(affinity_maps);
DEFINE_QOBJ_TYPE(affinity_map);
struct affinity_maps affinity_map_master = {NULL, NULL, NULL, NULL};
static void affinity_map_free(struct affinity_map *map)
{
XFREE(MTYPE_AFFINITY_MAP, map);
}
void affinity_map_set(const char *name, int pos)
{
struct listnode *node;
struct affinity_map *map;
if (!affinity_map_master.maps)
affinity_map_master.maps = list_new();
for (ALL_LIST_ELEMENTS_RO(affinity_map_master.maps, node, map)) {
if (strncmp(name, map->name, AFFINITY_NAME_SIZE) != 0)
continue;
map->bit_position = pos;
return;
}
map = XCALLOC(MTYPE_AFFINITY_MAP, sizeof(*map));
map->bit_position = pos;
snprintf(map->name, sizeof(map->name), "%s", name);
listnode_add(affinity_map_master.maps, map);
}
void affinity_map_unset(const char *name)
{
struct listnode *node, *nnode;
struct affinity_map *map;
if (!affinity_map_master.maps)
return;
for (ALL_LIST_ELEMENTS(affinity_map_master.maps, node, nnode, map)) {
if (strncmp(name, map->name, AFFINITY_NAME_SIZE) != 0)
continue;
listnode_delete(affinity_map_master.maps, map);
affinity_map_free(map);
return;
}
}
struct affinity_map *affinity_map_get(const char *name)
{
struct listnode *node;
struct affinity_map *map;
if (!affinity_map_master.maps)
return NULL;
for (ALL_LIST_ELEMENTS_RO(affinity_map_master.maps, node, map))
if (strncmp(name, map->name, AFFINITY_NAME_SIZE) == 0)
return map;
return NULL;
}
char *affinity_map_name_get(int pos)
{
struct listnode *node;
struct affinity_map *map;
if (!affinity_map_master.maps)
return NULL;
for (ALL_LIST_ELEMENTS_RO(affinity_map_master.maps, node, map))
if (map->bit_position == pos)
return map->name;
return NULL;
}
bool affinity_map_check_use_hook(const char *affmap_name)
{
if (affinity_map_master.check_use_hook)
return (*affinity_map_master.check_use_hook)(affmap_name);
return false;
}
bool affinity_map_check_update_hook(const char *affmap_name, uint16_t new_pos)
{
if (affinity_map_master.check_update_hook)
return (*affinity_map_master.check_update_hook)(affmap_name,
new_pos);
return true;
}
void affinity_map_update_hook(const char *affmap_name, uint16_t new_pos)
{
struct affinity_map *map;
if (!affinity_map_master.update_hook)
return;
map = affinity_map_get(affmap_name);
if (!map)
/* Affinity-map creation */
return;
(*affinity_map_master.update_hook)(affmap_name, map->bit_position,
new_pos);
}
void affinity_map_set_check_use_hook(bool (*func)(const char *affmap_name))
{
affinity_map_master.check_use_hook = func;
}
void affinity_map_set_check_update_hook(bool (*func)(const char *affmap_name,
uint16_t new_pos))
{
affinity_map_master.check_update_hook = func;
}
void affinity_map_set_update_hook(void (*func)(const char *affmap_name,
uint16_t old_pos,
uint16_t new_pos))
{
affinity_map_master.update_hook = func;
}

90
lib/affinitymap.h Normal file
View File

@ -0,0 +1,90 @@
/*
* Affinity-map function.
*
* Copyright 2022 Hiroki Shirokura, LINE Corporation
* Copyright 2022 Masakazu Asama
* Copyright 2022 6WIND S.A.
*
* This file is part of Free Range Routing (FRR).
*
* FRR is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* FRR is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; see the file COPYING; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _ZEBRA_AFFINITYMAP_H
#define _ZEBRA_AFFINITYMAP_H
#include "typesafe.h"
#include "prefix.h"
#include "memory.h"
#include "qobj.h"
#include "vty.h"
#include "lib/plist.h"
#include "lib/plist_int.h"
#ifdef __cplusplus
extern "C" {
#endif
#define AFFINITY_NAME_SIZE 32
struct affinity_map {
char name[AFFINITY_NAME_SIZE];
uint16_t bit_position;
QOBJ_FIELDS;
};
DECLARE_QOBJ_TYPE(affinity_map);
struct affinity_maps {
struct list *maps;
bool (*check_use_hook)(const char *affmap_name);
bool (*check_update_hook)(const char *affmap_name, uint16_t new_pos);
void (*update_hook)(const char *affmap_name, uint16_t old_pos,
uint16_t new_pos);
QOBJ_FIELDS;
};
DECLARE_QOBJ_TYPE(affinity_maps);
extern const struct frr_yang_module_info frr_affinity_map_info;
void affinity_map_set(const char *name, int pos);
void affinity_map_unset(const char *name);
struct affinity_map *affinity_map_get(const char *name);
char *affinity_map_name_get(const int pos);
bool affinity_map_check_use_hook(const char *affmap_name);
bool affinity_map_check_update_hook(const char *affmap_name, uint16_t new_pos);
void affinity_map_update_hook(const char *affmap_name, uint16_t new_pos);
void affinity_map_set_check_use_hook(bool (*func)(const char *affmap_name));
void affinity_map_set_check_update_hook(bool (*func)(const char *affmap_name,
uint16_t new_pos));
void affinity_map_set_update_hook(void (*func)(const char *affmap_name,
uint16_t old_pos,
uint16_t new_pos));
void cli_show_affinity_map(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
void affinity_map_init(void);
#ifdef __cplusplus
}
#endif
#endif /* _ZEBRA_AFFINITYMAP_H */

107
lib/affinitymap_cli.c Normal file
View File

@ -0,0 +1,107 @@
/*
* Affinity map northbound CLI implementation.
*
* Copyright 2022 Hiroki Shirokura, LINE Corporation
* Copyright 2022 Masakazu Asama
* Copyright 2022 6WIND S.A.
*
*
* This file is part of Free Range Routing (FRR).
*
* FRR is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* FRR is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; see the file COPYING; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
#include "lib/command.h"
#include "lib/northbound_cli.h"
#include "lib/affinitymap.h"
#include "lib/affinitymap_cli_clippy.c"
/* Route map node structure. */
static int affinity_map_config_write(struct vty *vty);
static struct cmd_node affinitymap_node = {
.name = "affinity-map",
.node = AFFMAP_NODE,
.prompt = "",
.config_write = affinity_map_config_write,
};
/* max value is EXT_ADMIN_GROUP_MAX_POSITIONS - 1 */
DEFPY_YANG_NOSH(affinity_map, affinity_map_cmd,
"affinity-map NAME$name bit-position (0-1023)$position",
"Affinity map configuration\n"
"Affinity attribute name\n"
"Bit position for affinity attribute value\n"
"Bit position\n")
{
char xpathr[XPATH_MAXLEN];
snprintf(
xpathr, sizeof(xpathr),
"/frr-affinity-map:lib/affinity-maps/affinity-map[name='%s']/value",
name);
nb_cli_enqueue_change(vty, xpathr, NB_OP_MODIFY, position_str);
return nb_cli_apply_changes(vty, NULL);
}
/* max value is EXT_ADMIN_GROUP_MAX_POSITIONS - 1 */
DEFPY_YANG_NOSH(no_affinity_map, no_affinity_map_cmd,
"no affinity-map NAME$name [bit-position (0-1023)$position]",
NO_STR
"Affinity map configuration\n"
"Affinity attribute name\n"
"Bit position for affinity attribute value\n"
"Bit position\n")
{
char xpathr[XPATH_MAXLEN];
snprintf(xpathr, sizeof(xpathr),
"/frr-affinity-map:lib/affinity-maps/affinity-map[name='%s']",
name);
nb_cli_enqueue_change(vty, xpathr, NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(vty, NULL);
}
static int affinity_map_config_write(struct vty *vty)
{
const struct lyd_node *dnode;
int written = 0;
dnode = yang_dnode_get(running_config->dnode, "/frr-affinity-map:lib");
if (dnode) {
nb_cli_show_dnode_cmds(vty, dnode, false);
written = 1;
}
return written;
}
void cli_show_affinity_map(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults __attribute__((__unused__)))
{
vty_out(vty, "affinity-map %s bit-position %u\n",
yang_dnode_get_string(dnode, "./name"),
yang_dnode_get_uint16(dnode, "./value"));
}
/* Initialization of affinity map vector. */
void affinity_map_init(void)
{
/* CLI commands. */
install_node(&affinitymap_node);
install_element(CONFIG_NODE, &affinity_map_cmd);
install_element(CONFIG_NODE, &no_affinity_map_cmd);
}

View File

@ -0,0 +1,136 @@
/*
* affinity map northbound implementation.
*
* Copyright 2022 Hiroki Shirokura, LINE Corporation
* Copyright 2022 Masakazu Asama
* Copyright 2022 6WIND S.A.
*
* This file is part of Free Range Routing (FRR).
*
* FRR is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* FRR is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; see the file COPYING; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
#include "lib/command.h"
#include "lib/log.h"
#include "lib/northbound.h"
#include "lib/affinitymap.h"
/*
* XPath: /frr-affinity-map:lib/affinity-maps/affinity-map
*/
static int lib_affinity_map_create(struct nb_cb_create_args *args)
{
return NB_OK;
}
static int lib_affinity_map_destroy(struct nb_cb_destroy_args *args)
{
const char *name;
name = yang_dnode_get_string((const struct lyd_node *)args->dnode,
"./name");
switch (args->event) {
case NB_EV_VALIDATE:
if (!affinity_map_check_use_hook(name))
break;
snprintf(args->errmsg, args->errmsg_len,
"affinity-map %s is used", name);
return NB_ERR_VALIDATION;
case NB_EV_PREPARE:
case NB_EV_ABORT:
break;
case NB_EV_APPLY:
affinity_map_unset(name);
break;
}
return NB_OK;
}
/*
* XPath: /frr-affinity-map:lib/affinity-maps/affinity-map/value
*/
static int lib_affinity_map_value_modify(struct nb_cb_modify_args *args)
{
const char *name;
char *map_name;
uint16_t pos;
name = yang_dnode_get_string(
(const struct lyd_node *)args->dnode->parent, "./name");
pos = yang_dnode_get_uint16(
(const struct lyd_node *)args->dnode->parent, "./value");
switch (args->event) {
case NB_EV_VALIDATE:
map_name = affinity_map_name_get(pos);
if (map_name &&
strncmp(map_name, name, AFFINITY_NAME_SIZE) != 0) {
snprintf(args->errmsg, args->errmsg_len,
"bit-position is used by %s.", map_name);
return NB_ERR_VALIDATION;
}
if (!affinity_map_check_update_hook(name, pos)) {
snprintf(
args->errmsg, args->errmsg_len,
"affinity-map new bit-position > 31 but is used with standard admin-groups");
return NB_ERR_VALIDATION;
}
break;
case NB_EV_PREPARE:
case NB_EV_ABORT:
break;
case NB_EV_APPLY:
affinity_map_update_hook(name, pos);
affinity_map_set(name, pos);
break;
}
return NB_OK;
}
static int lib_affinity_map_value_destroy(struct nb_cb_destroy_args *args)
{
return NB_OK;
}
/* clang-format off */
const struct frr_yang_module_info frr_affinity_map_info = {
.name = "frr-affinity-map",
.nodes = {
{
.xpath = "/frr-affinity-map:lib/affinity-maps/affinity-map",
.cbs = {
.create = lib_affinity_map_create,
.destroy = lib_affinity_map_destroy,
.cli_show = cli_show_affinity_map,
}
},
{
.xpath = "/frr-affinity-map:lib/affinity-maps/affinity-map/value",
.cbs = {
.modify = lib_affinity_map_value_modify,
.destroy = lib_affinity_map_value_destroy,
}
},
{
.xpath = NULL,
},
}
};

View File

@ -72,7 +72,8 @@ DECLARE_MTYPE(BITFIELD);
do { \
(v).n = 0; \
(v).m = ((N) / WORD_SIZE + 1); \
(v).data = XCALLOC(MTYPE_BITFIELD, ((v).m * sizeof(word_t))); \
(v).data = (word_t *)XCALLOC(MTYPE_BITFIELD, \
((v).m * sizeof(word_t))); \
} while (0)
/**
@ -268,6 +269,19 @@ static inline unsigned int bf_find_next_set_bit(bitfield_t v,
(v).data = NULL; \
} while (0)
static inline bitfield_t bf_copy(bitfield_t src)
{
bitfield_t dst;
assert(bf_is_inited(src));
bf_init(dst, WORD_SIZE * (src.m - 1));
for (size_t i = 0; i < src.m; i++)
dst.data[i] = src.data[i];
dst.n = src.n;
return dst;
}
#ifdef __cplusplus
}
#endif

View File

@ -90,6 +90,7 @@ struct host {
};
/* List of CLI nodes. Please remember to update the name array in command.c. */
/* clang-format off */
enum node_type {
AUTH_NODE, /* Authentication mode of vty interface. */
VIEW_NODE, /* View node. Default mode of vty interface. */
@ -106,6 +107,7 @@ enum node_type {
EXTLOG_NODE, /* RFC5424 & co. extended syslog */
KEYCHAIN_NODE, /* Key-chain node. */
KEYCHAIN_KEY_NODE, /* Key-chain key node. */
AFFMAP_NODE, /* Affinity map node. */
IP_NODE, /* Static ip route node. */
VRF_NODE, /* VRF mode node. */
INTERFACE_NODE, /* Interface mode node. */
@ -186,6 +188,7 @@ enum node_type {
BMP_NODE, /* BMP config under router bgp */
NODE_TYPE_MAX, /* maximum */
};
/* clang-format on */
extern vector cmdvec;
extern const struct message tokennames[];

View File

@ -35,6 +35,7 @@
#include "buffer.h"
#include "log.h"
#include "northbound_cli.h"
#include "admin_group.h"
#include "lib/if_clippy.c"
DEFINE_MTYPE_STATIC(LIB, IF, "Interface");
@ -1106,6 +1107,45 @@ const char *if_link_type_str(enum zebra_link_type llt)
return NULL;
}
bool if_link_params_cmp(struct if_link_params *iflp1,
struct if_link_params *iflp2)
{
struct if_link_params iflp1_copy, iflp2_copy;
/* Extended admin-groups in if_link_params contain pointers.
* They cannot be compared with memcpy.
* Make copies of if_link_params without ext. admin-groups
* and compare separately the ext. admin-groups.
*/
memcpy(&iflp1_copy, iflp1, sizeof(struct if_link_params));
memset(&iflp1_copy.ext_admin_grp, 0, sizeof(struct admin_group));
memcpy(&iflp2_copy, iflp2, sizeof(struct if_link_params));
memset(&iflp2_copy.ext_admin_grp, 0, sizeof(struct admin_group));
if (memcmp(&iflp1_copy, &iflp2_copy, sizeof(struct if_link_params)))
return false;
if (!admin_group_cmp(&iflp1->ext_admin_grp, &iflp2->ext_admin_grp))
return false;
return true;
}
void if_link_params_copy(struct if_link_params *dst, struct if_link_params *src)
{
struct admin_group dst_ag;
/* backup the admin_group structure that contains a pointer */
memcpy(&dst_ag, &dst->ext_admin_grp, sizeof(struct admin_group));
/* copy the if_link_params structure */
memcpy(dst, src, sizeof(struct if_link_params));
/* restore the admin_group structure */
memcpy(&dst->ext_admin_grp, &dst_ag, sizeof(struct admin_group));
/* copy src->ext_admin_grp data to dst->ext_admin_grp data memory */
admin_group_copy(&dst->ext_admin_grp, &src->ext_admin_grp);
}
struct if_link_params *if_link_params_get(struct interface *ifp)
{
return ifp->link_params;
@ -1153,6 +1193,8 @@ struct if_link_params *if_link_params_init(struct interface *ifp)
iflp = XCALLOC(MTYPE_IF_LINK_PARAMS, sizeof(struct if_link_params));
admin_group_init(&iflp->ext_admin_grp);
ifp->link_params = iflp;
return iflp;
@ -1160,6 +1202,10 @@ struct if_link_params *if_link_params_init(struct interface *ifp)
void if_link_params_free(struct interface *ifp)
{
if (!ifp->link_params)
return;
admin_group_term(&ifp->link_params->ext_admin_grp);
XFREE(MTYPE_IF_LINK_PARAMS, ifp->link_params);
}

View File

@ -26,6 +26,7 @@
#include "memory.h"
#include "qobj.h"
#include "hook.h"
#include "admin_group.h"
#ifdef __cplusplus
extern "C" {
@ -153,6 +154,15 @@ struct if_stats {
#define MAX_CLASS_TYPE 8
#define MAX_PKT_LOSS 50.331642
enum affinity_mode {
/* RFC7308 Extended Administrative group */
AFFINITY_MODE_EXTENDED = 0,
/* RFC3630/RFC5305/RFC5329 Administrative group */
AFFINITY_MODE_STANDARD = 1,
/* Standard and Extended Administrative group */
AFFINITY_MODE_BOTH = 2,
};
/*
* Link Parameters Status:
* equal to 0: unset
@ -172,6 +182,7 @@ struct if_stats {
#define LP_RES_BW 0x0400
#define LP_AVA_BW 0x0800
#define LP_USE_BW 0x1000
#define LP_EXTEND_ADM_GRP 0x2000
#define IS_PARAM_UNSET(lp, st) !(lp->lp_status & st)
#define IS_PARAM_SET(lp, st) (lp->lp_status & st)
@ -181,7 +192,10 @@ struct if_stats {
#define UNSET_PARAM(lp, st) (lp->lp_status) &= ~(st)
#define RESET_LINK_PARAM(lp) (lp->lp_status = LP_UNSET)
/* Link Parameters for Traffic Engineering */
/* Link Parameters for Traffic Engineering
* Do not forget to update if_link_params_copy()
* and if_link_params_cmp() when updating the structure
*/
struct if_link_params {
uint32_t lp_status; /* Status of Link Parameters: */
uint32_t te_metric; /* Traffic Engineering metric */
@ -190,7 +204,8 @@ struct if_link_params {
float max_rsv_bw; /* Maximum Reservable Bandwidth */
float unrsv_bw[MAX_CLASS_TYPE]; /* Unreserved Bandwidth per Class Type
(8) */
uint32_t admin_grp; /* Administrative group */
uint32_t admin_grp; /* RFC5305/RFC5329 Administrative group */
struct admin_group ext_admin_grp; /* RFC7308 Extended Admin group */
uint32_t rmt_as; /* Remote AS number */
struct in_addr rmt_ip; /* Remote IP address */
uint32_t av_delay; /* Link Average Delay */
@ -592,6 +607,10 @@ struct nbr_connected *nbr_connected_check(struct interface *, struct prefix *);
struct connected *connected_get_linklocal(struct interface *ifp);
/* link parameters */
bool if_link_params_cmp(struct if_link_params *iflp1,
struct if_link_params *iflp2);
void if_link_params_copy(struct if_link_params *dst,
struct if_link_params *src);
struct if_link_params *if_link_params_get(struct interface *);
struct if_link_params *if_link_params_enable(struct interface *ifp);
struct if_link_params *if_link_params_init(struct interface *ifp);

View File

@ -192,6 +192,8 @@ struct ls_attributes *ls_attributes_new(struct ls_node_id adv,
return NULL;
}
admin_group_init(&new->ext_admin_group);
return new;
}
@ -215,6 +217,8 @@ void ls_attributes_del(struct ls_attributes *attr)
ls_attributes_srlg_del(attr);
admin_group_term(&attr->ext_admin_group);
XFREE(MTYPE_LS_DB, attr);
}
@ -246,6 +250,9 @@ int ls_attributes_same(struct ls_attributes *l1, struct ls_attributes *l2)
if (CHECK_FLAG(l1->flags, LS_ATTR_ADM_GRP)
&& (l1->standard.admin_group != l2->standard.admin_group))
return 0;
if (CHECK_FLAG(l1->flags, LS_ATTR_EXT_ADM_GRP) &&
!admin_group_cmp(&l1->ext_admin_group, &l2->ext_admin_group))
return 0;
if (CHECK_FLAG(l1->flags, LS_ATTR_LOCAL_ADDR)
&& !IPV4_ADDR_SAME(&l1->standard.local, &l2->standard.local))
return 0;
@ -1206,9 +1213,12 @@ stream_failure:
static struct ls_attributes *ls_parse_attributes(struct stream *s)
{
struct ls_attributes *attr;
uint8_t nb_ext_adm_grp;
uint32_t bitmap_data;
size_t len;
attr = XCALLOC(MTYPE_LS_DB, sizeof(struct ls_attributes));
admin_group_init(&attr->ext_admin_group);
attr->srlgs = NULL;
STREAM_GET(&attr->adv, s, sizeof(struct ls_node_id));
@ -1223,6 +1233,15 @@ static struct ls_attributes *ls_parse_attributes(struct stream *s)
STREAM_GETL(s, attr->standard.te_metric);
if (CHECK_FLAG(attr->flags, LS_ATTR_ADM_GRP))
STREAM_GETL(s, attr->standard.admin_group);
if (CHECK_FLAG(attr->flags, LS_ATTR_EXT_ADM_GRP)) {
/* Extended Administrative Group */
STREAM_GETC(s, nb_ext_adm_grp);
for (size_t i = 0; i < nb_ext_adm_grp; i++) {
STREAM_GETL(s, bitmap_data);
admin_group_bulk_set(&attr->ext_admin_group,
bitmap_data, i);
}
}
if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR))
attr->standard.local.s_addr = stream_get_ipv4(s);
if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ADDR))
@ -1430,7 +1449,7 @@ static int ls_format_node(struct stream *s, struct ls_node *node)
static int ls_format_attributes(struct stream *s, struct ls_attributes *attr)
{
size_t len;
size_t len, nb_ext_adm_grp;
/* Push Advertise node information first */
stream_put(s, &attr->adv, sizeof(struct ls_node_id));
@ -1449,6 +1468,14 @@ static int ls_format_attributes(struct stream *s, struct ls_attributes *attr)
stream_putl(s, attr->standard.te_metric);
if (CHECK_FLAG(attr->flags, LS_ATTR_ADM_GRP))
stream_putl(s, attr->standard.admin_group);
if (CHECK_FLAG(attr->flags, LS_ATTR_EXT_ADM_GRP)) {
/* Extended Administrative Group */
nb_ext_adm_grp = admin_group_nb_words(&attr->ext_admin_group);
stream_putc(s, nb_ext_adm_grp);
for (size_t i = 0; i < nb_ext_adm_grp; i++)
stream_putl(s, admin_group_get_offset(
&attr->ext_admin_group, i));
}
if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR))
stream_put_ipv4(s, attr->standard.local.s_addr);
if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ADDR))
@ -2166,9 +2193,11 @@ void ls_show_vertices(struct ls_ted *ted, struct vty *vty,
static void ls_show_edge_vty(struct ls_edge *edge, struct vty *vty,
bool verbose)
{
char admin_group_buf[ADMIN_GROUP_PRINT_MAX_SIZE];
struct ls_attributes *attr;
struct sbuf sbuf;
char buf[INET6_BUFSIZ];
int indent;
attr = edge->attributes;
sbuf_init(&sbuf, NULL, 0);
@ -2198,6 +2227,20 @@ static void ls_show_edge_vty(struct ls_edge *edge, struct vty *vty,
if (CHECK_FLAG(attr->flags, LS_ATTR_ADM_GRP))
sbuf_push(&sbuf, 4, "Admin Group: 0x%x\n",
attr->standard.admin_group);
if (CHECK_FLAG(attr->flags, LS_ATTR_EXT_ADM_GRP) &&
admin_group_nb_words(&attr->ext_admin_group) != 0) {
indent = 4;
sbuf_push(&sbuf, indent, "Ext Admin Group: %s\n",
admin_group_string(
admin_group_buf, ADMIN_GROUP_PRINT_MAX_SIZE,
indent + strlen("Ext Admin Group: "),
&attr->ext_admin_group));
if (admin_group_buf[0] != '\0' &&
(sbuf.pos + strlen(admin_group_buf) +
SBUF_DEFAULT_SIZE / 2) < sbuf.size)
sbuf_push(&sbuf, indent + 2, "Bit positions: %s\n",
admin_group_buf);
}
if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR))
sbuf_push(&sbuf, 4, "Local IPv4 address: %pI4\n",
&attr->standard.local);
@ -2308,8 +2351,13 @@ end:
static void ls_show_edge_json(struct ls_edge *edge, struct json_object *json)
{
struct ls_attributes *attr;
struct json_object *jte, *jbw, *jobj, *jsr = NULL, *jsrlg;
struct json_object *jte, *jbw, *jobj, *jsr = NULL, *jsrlg, *js_ext_ag,
*js_ext_ag_arr_word,
*js_ext_ag_arr_bit;
char buf[INET6_BUFSIZ];
char buf_ag[strlen("0xffffffff") + 1];
uint32_t bitmap;
size_t i;
attr = edge->attributes;
@ -2333,6 +2381,30 @@ static void ls_show_edge_json(struct ls_edge *edge, struct json_object *json)
if (CHECK_FLAG(attr->flags, LS_ATTR_ADM_GRP))
json_object_int_add(jte, "admin-group",
attr->standard.admin_group);
if (CHECK_FLAG(attr->flags, LS_ATTR_EXT_ADM_GRP)) {
js_ext_ag = json_object_new_object();
json_object_object_add(jte, "extAdminGroup", js_ext_ag);
js_ext_ag_arr_word = json_object_new_array();
json_object_object_add(js_ext_ag, "words", js_ext_ag_arr_word);
js_ext_ag_arr_bit = json_object_new_array();
json_object_object_add(js_ext_ag, "bitPositions",
js_ext_ag_arr_bit);
for (i = 0; i < admin_group_nb_words(&attr->ext_admin_group);
i++) {
bitmap = admin_group_get_offset(&attr->ext_admin_group,
i);
snprintf(buf_ag, sizeof(buf_ag), "0x%08x", bitmap);
json_object_array_add(js_ext_ag_arr_word,
json_object_new_string(buf_ag));
}
for (i = 0;
i < (admin_group_size(&attr->ext_admin_group) * WORD_SIZE);
i++) {
if (admin_group_get(&attr->ext_admin_group, i))
json_object_array_add(js_ext_ag_arr_bit,
json_object_new_int(i));
}
}
if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR)) {
snprintfrr(buf, INET6_BUFSIZ, "%pI4", &attr->standard.local);
json_object_string_add(jte, "local-address", buf);

View File

@ -25,6 +25,7 @@
#ifndef _FRR_LINK_STATE_H_
#define _FRR_LINK_STATE_H_
#include "admin_group.h"
#include "typesafe.h"
#ifdef __cplusplus
@ -169,6 +170,7 @@ struct ls_node {
#define LS_ATTR_ADJ_SID6 0x04000000
#define LS_ATTR_BCK_ADJ_SID6 0x08000000
#define LS_ATTR_SRLG 0x10000000
#define LS_ATTR_EXT_ADM_GRP 0x20000000
/* Link State Attributes */
struct ls_attributes {
@ -202,6 +204,7 @@ struct ls_attributes {
float rsv_bw; /* Reserved Bandwidth */
float used_bw; /* Utilized Bandwidth */
} extended;
struct admin_group ext_admin_group; /* Extended Admin. Group */
#define ADJ_PRI_IPV4 0
#define ADJ_BCK_IPV4 1
#define ADJ_PRI_IPV6 2

View File

@ -33,8 +33,8 @@ void sbuf_init(struct sbuf *dest, char *buf, size_t size)
dest->buf = buf;
dest->size = size;
} else {
dest->buf = XMALLOC(MTYPE_TMP, 4096);
dest->size = 4096;
dest->buf = XMALLOC(MTYPE_TMP, SBUF_DEFAULT_SIZE);
dest->size = SBUF_DEFAULT_SIZE;
}
dest->pos = 0;

View File

@ -64,6 +64,8 @@ extern "C" {
* the string returned in parser_log.
*/
#define SBUF_DEFAULT_SIZE 8192
struct sbuf {
bool fixed;
char *buf;

View File

@ -7,6 +7,10 @@ lib_libfrr_la_LDFLAGS = $(LIB_LDFLAGS) -version-info 0:0:0 -Xlinker -e_libfrr_ve
lib_libfrr_la_LIBADD = $(LIBCAP) $(UNWIND_LIBS) $(LIBYANG_LIBS) $(LUA_LIB) $(UST_LIBS) $(LIBCRYPT) $(LIBDL) $(LIBM)
lib_libfrr_la_SOURCES = \
lib/admin_group.c \
lib/affinitymap.c \
lib/affinitymap_cli.c \
lib/affinitymap_northbound.c \
lib/agg_table.c \
lib/atomlist.c \
lib/base64.c \
@ -127,6 +131,7 @@ lib_libfrr_la_SOURCES = \
# end
nodist_lib_libfrr_la_SOURCES = \
yang/frr-affinity-map.yang.c \
yang/frr-filter.yang.c \
yang/frr-interface.yang.c \
yang/frr-route-map.yang.c \
@ -146,6 +151,7 @@ lib_libfrr_la_SOURCES += lib/db.c
endif
clippy_scan += \
lib/affinitymap_cli.c \
lib/if.c \
lib/filter_cli.c \
lib/log_vty.c \
@ -160,6 +166,8 @@ clippy_scan += \
# end
pkginclude_HEADERS += \
lib/admin_group.h \
lib/affinitymap.h \
lib/agg_table.h \
lib/atomlist.h \
lib/base64.h \

View File

@ -88,6 +88,7 @@ static const char *const frr_native_modules[] = {
"frr-interface",
"frr-vrf",
"frr-routing",
"frr-affinity-map",
"frr-route-map",
"frr-nexthop",
"frr-ripd",

View File

@ -2405,9 +2405,9 @@ static int zclient_handle_error(ZAPI_CALLBACK_ARGS)
static int link_params_set_value(struct stream *s, struct interface *ifp)
{
uint8_t link_params_enabled;
uint8_t link_params_enabled, nb_ext_adm_grp;
struct if_link_params *iflp;
uint32_t bwclassnum;
uint32_t bwclassnum, bitmap_data;
iflp = if_link_params_get(ifp);
@ -2436,6 +2436,15 @@ static int link_params_set_value(struct stream *s, struct interface *ifp)
__func__, bwclassnum, MAX_CLASS_TYPE);
}
STREAM_GETL(s, iflp->admin_grp);
/* Extended Administrative Group */
admin_group_clear(&iflp->ext_admin_grp);
STREAM_GETC(s, nb_ext_adm_grp);
for (size_t i = 0; i < nb_ext_adm_grp; i++) {
STREAM_GETL(s, bitmap_data);
admin_group_bulk_set(&iflp->ext_admin_grp, bitmap_data, i);
}
STREAM_GETL(s, iflp->rmt_as);
iflp->rmt_ip.s_addr = stream_get_ipv4(s);
@ -2459,9 +2468,9 @@ struct interface *zebra_interface_link_params_read(struct stream *s,
bool *changed)
{
struct if_link_params *iflp;
struct if_link_params iflp_prev;
struct if_link_params iflp_prev = {0};
ifindex_t ifindex;
bool iflp_prev_set;
bool iflp_prev_set = false;
STREAM_GETL(s, ifindex);
@ -2474,11 +2483,13 @@ struct interface *zebra_interface_link_params_read(struct stream *s,
return NULL;
}
if (if_link_params_get(ifp)) {
iflp = if_link_params_get(ifp);
if (iflp) {
iflp_prev_set = true;
memcpy(&iflp_prev, ifp->link_params, sizeof(iflp_prev));
} else
iflp_prev_set = false;
admin_group_init(&iflp_prev.ext_admin_grp);
if_link_params_copy(&iflp_prev, iflp);
}
/* read the link_params from stream
* Free ifp->link_params if the stream has no params
@ -2487,24 +2498,28 @@ struct interface *zebra_interface_link_params_read(struct stream *s,
if (link_params_set_value(s, ifp) != 0)
goto stream_failure;
if (changed == NULL)
return ifp;
if (changed != NULL) {
iflp = if_link_params_get(ifp);
iflp = if_link_params_get(ifp);
if (iflp_prev_set && iflp) {
if (memcmp(&iflp_prev, iflp, sizeof(iflp_prev)))
*changed = true;
else
if (iflp_prev_set && iflp) {
if (if_link_params_cmp(&iflp_prev, iflp))
*changed = false;
else
*changed = true;
} else if (!iflp_prev_set && !iflp)
*changed = false;
} else if (!iflp_prev_set && !iflp)
*changed = false;
else
*changed = true;
else
*changed = true;
}
if (iflp_prev_set)
admin_group_term(&iflp_prev.ext_admin_grp);
return ifp;
stream_failure:
if (iflp_prev_set)
admin_group_term(&iflp_prev.ext_admin_grp);
return NULL;
}
@ -2553,10 +2568,11 @@ stream_failure:
size_t zebra_interface_link_params_write(struct stream *s,
struct interface *ifp)
{
size_t w;
size_t w, nb_ext_adm_grp;
struct if_link_params *iflp;
int i;
if (s == NULL || ifp == NULL)
return 0;
@ -2582,6 +2598,13 @@ size_t zebra_interface_link_params_write(struct stream *s,
w += stream_putf(s, iflp->unrsv_bw[i]);
w += stream_putl(s, iflp->admin_grp);
/* Extended Administrative Group */
nb_ext_adm_grp = admin_group_nb_words(&iflp->ext_admin_grp);
w += stream_putc(s, nb_ext_adm_grp);
for (size_t i = 0; i < nb_ext_adm_grp; i++)
stream_putl(s, admin_group_get_offset(&iflp->ext_admin_grp, i));
w += stream_putl(s, iflp->rmt_as);
w += stream_put_in_addr(s, &iflp->rmt_ip);

View File

@ -0,0 +1,969 @@
{
"ted":{
"name":"ISIS",
"key":1,
"verticesCount":4,
"edgesCount":16,
"subnetsCount":24,
"vertices":[
{
"vertex-id":1,
"status":"Sync",
"origin":"ISIS_L2",
"name":"r1",
"router-id":"10.0.255.1"
},
{
"vertex-id":2,
"status":"Sync",
"origin":"ISIS_L2",
"name":"r2",
"router-id":"10.0.255.2"
},
{
"vertex-id":3,
"status":"Sync",
"origin":"ISIS_L2",
"name":"r3",
"router-id":"10.0.255.3",
"router-id-v6":"2001:db8:1000::3"
},
{
"vertex-id":4,
"status":"Sync",
"origin":"ISIS_L2",
"name":"r4",
"router-id":"10.0.255.4",
"segment-routing":{
"srgb-size":10000,
"srgb-lower":10000,
"algorithms":[
{
"0":"SPF"
}
],
"srlb-size":1000,
"srlb-lower":5000,
"msd":12
}
}
],
"edges":[
{
"edge-id":1,
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0001",
"local-vertex-id":1,
"remote-vertex-id":2,
"metric":10,
"edge-attributes":{
"te-metric":20,
"extAdminGroup":{
"words":[
"0x80000001",
"0x00000000",
"0x00000000",
"0x00000000",
"0x00000001"
],
"bitPositions":[
0,
31,
128
]
},
"local-address-v6":"2001:db8::1",
"remote-address-v6":"2001:db8::2",
"max-link-bandwidth":99999997952,
"max-resv-link-bandwidth":1250000,
"unreserved-bandwidth":[
{
"class-type-0":1250000
},
{
"class-type-1":1250000
},
{
"class-type-2":1250000
},
{
"class-type-3":1250000
},
{
"class-type-4":1250000
},
{
"class-type-5":1250000
},
{
"class-type-6":1250000
},
{
"class-type-7":1250000
}
],
"delay":10000,
"available-bandwidth":125000000.0
}
},
{
"edge-id":2,
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0002",
"local-vertex-id":2,
"remote-vertex-id":1,
"metric":10,
"edge-attributes":{
"local-address-v6":"2001:db8::2",
"max-link-bandwidth":1250000,
"max-resv-link-bandwidth":1250000,
"unreserved-bandwidth":[
{
"class-type-0":1250000
},
{
"class-type-1":1250000
},
{
"class-type-2":1250000
},
{
"class-type-3":1250000
},
{
"class-type-4":1250000
},
{
"class-type-5":1250000
},
{
"class-type-6":1250000
},
{
"class-type-7":1250000
}
]
}
},
{
"edge-id":65537,
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0001",
"local-vertex-id":1,
"remote-vertex-id":2,
"metric":10,
"edge-attributes":{
"local-address-v6":"2001:db8:1::1:1",
"remote-address-v6":"2001:db8:1::1:2",
"max-link-bandwidth":1250000,
"max-resv-link-bandwidth":1250000,
"unreserved-bandwidth":[
{
"class-type-0":1250000
},
{
"class-type-1":1250000
},
{
"class-type-2":1250000
},
{
"class-type-3":1250000
},
{
"class-type-4":1250000
},
{
"class-type-5":1250000
},
{
"class-type-6":1250000
},
{
"class-type-7":1250000
}
]
}
},
{
"edge-id":65538,
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0002",
"local-vertex-id":2,
"remote-vertex-id":1,
"metric":10,
"edge-attributes":{
"local-address-v6":"2001:db8:1::1:2",
"remote-address-v6":"2001:db8:1::1:1",
"max-link-bandwidth":1250000,
"max-resv-link-bandwidth":1250000,
"unreserved-bandwidth":[
{
"class-type-0":1250000
},
{
"class-type-1":1250000
},
{
"class-type-2":1250000
},
{
"class-type-3":1250000
},
{
"class-type-4":1250000
},
{
"class-type-5":1250000
},
{
"class-type-6":1250000
},
{
"class-type-7":1250000
}
]
}
},
{
"edge-id":196610,
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0002",
"local-vertex-id":2,
"remote-vertex-id":3,
"metric":10,
"edge-attributes":{
"local-address-v6":"2001:db8:3::3:2",
"remote-address-v6":"2001:db8:3::3:3",
"max-link-bandwidth":1250000,
"max-resv-link-bandwidth":1250000,
"unreserved-bandwidth":[
{
"class-type-0":1250000
},
{
"class-type-1":1250000
},
{
"class-type-2":1250000
},
{
"class-type-3":1250000
},
{
"class-type-4":1250000
},
{
"class-type-5":1250000
},
{
"class-type-6":1250000
},
{
"class-type-7":1250000
}
]
}
},
{
"edge-id":196611,
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0003",
"local-vertex-id":3,
"remote-vertex-id":2,
"metric":10,
"edge-attributes":{
"admin-group":32,
"local-address-v6":"2001:db8:3::3:3",
"remote-address-v6":"2001:db8:3::3:2",
"max-link-bandwidth":1250000,
"max-resv-link-bandwidth":1250000,
"unreserved-bandwidth":[
{
"class-type-0":1250000
},
{
"class-type-1":1250000
},
{
"class-type-2":1250000
},
{
"class-type-3":1250000
},
{
"class-type-4":1250000
},
{
"class-type-5":1250000
},
{
"class-type-6":1250000
},
{
"class-type-7":1250000
}
]
}
},
{
"edge-id":196612,
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0004",
"local-vertex-id":4,
"remote-vertex-id":3,
"metric":10,
"edge-attributes":{
"local-address-v6":"2001:db8:5::3:4",
"remote-address-v6":"2001:db8:5::4:3",
"max-link-bandwidth":1250000,
"max-resv-link-bandwidth":1250000,
"unreserved-bandwidth":[
{
"class-type-0":1250000
},
{
"class-type-1":1250000
},
{
"class-type-2":1250000
},
{
"class-type-3":1250000
},
{
"class-type-4":1250000
},
{
"class-type-5":1250000
},
{
"class-type-6":1250000
},
{
"class-type-7":1250000
}
]
},
"segment-routing":[
{
"adj-sid":5001,
"flags":"0xb0",
"weight":0
}
]
},
{
"edge-id":262147,
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0003",
"local-vertex-id":3,
"remote-vertex-id":4,
"metric":10,
"edge-attributes":{
"te-metric":10,
"local-address-v6":"2001:db8:5::4:3",
"remote-address-v6":"2001:db8:5::3:4",
"max-link-bandwidth":1250000,
"max-resv-link-bandwidth":1250000,
"unreserved-bandwidth":[
{
"class-type-0":1250000
},
{
"class-type-1":1250000
},
{
"class-type-2":1250000
},
{
"class-type-3":1250000
},
{
"class-type-4":1250000
},
{
"class-type-5":1250000
},
{
"class-type-6":1250000
},
{
"class-type-7":1250000
}
],
"delay":50000
}
},
{
"edge-id":167772161,
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0001",
"local-vertex-id":1,
"remote-vertex-id":2,
"metric":10,
"edge-attributes":{
"te-metric":20,
"extAdminGroup":{
"words":[
"0x80000001",
"0x00000000",
"0x00000000",
"0x00000000",
"0x00000001"
],
"bitPositions":[
0,
31,
128
]
},
"local-address":"10.0.0.1",
"remote-address":"10.0.0.2",
"max-link-bandwidth":99999997952,
"max-resv-link-bandwidth":1250000,
"unreserved-bandwidth":[
{
"class-type-0":1250000
},
{
"class-type-1":1250000
},
{
"class-type-2":1250000
},
{
"class-type-3":1250000
},
{
"class-type-4":1250000
},
{
"class-type-5":1250000
},
{
"class-type-6":1250000
},
{
"class-type-7":1250000
}
],
"delay":10000,
"available-bandwidth":125000000.0
}
},
{
"edge-id":167772162,
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0002",
"local-vertex-id":2,
"remote-vertex-id":1,
"metric":10,
"edge-attributes":{
"local-address":"10.0.0.2",
"remote-address":"10.0.0.1",
"max-link-bandwidth":1250000,
"max-resv-link-bandwidth":1250000,
"unreserved-bandwidth":[
{
"class-type-0":1250000
},
{
"class-type-1":1250000
},
{
"class-type-2":1250000
},
{
"class-type-3":1250000
},
{
"class-type-4":1250000
},
{
"class-type-5":1250000
},
{
"class-type-6":1250000
},
{
"class-type-7":1250000
}
]
}
},
{
"edge-id":167772417,
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0001",
"local-vertex-id":1,
"remote-vertex-id":2,
"metric":10,
"edge-attributes":{
"local-address":"10.0.1.1",
"remote-address":"10.0.1.2",
"max-link-bandwidth":1250000,
"max-resv-link-bandwidth":1250000,
"unreserved-bandwidth":[
{
"class-type-0":1250000
},
{
"class-type-1":1250000
},
{
"class-type-2":1250000
},
{
"class-type-3":1250000
},
{
"class-type-4":1250000
},
{
"class-type-5":1250000
},
{
"class-type-6":1250000
},
{
"class-type-7":1250000
}
]
}
},
{
"edge-id":167772418,
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0002",
"local-vertex-id":2,
"remote-vertex-id":1,
"metric":10,
"edge-attributes":{
"local-address":"10.0.1.2",
"remote-address":"10.0.1.1",
"max-link-bandwidth":1250000,
"max-resv-link-bandwidth":1250000,
"unreserved-bandwidth":[
{
"class-type-0":1250000
},
{
"class-type-1":1250000
},
{
"class-type-2":1250000
},
{
"class-type-3":1250000
},
{
"class-type-4":1250000
},
{
"class-type-5":1250000
},
{
"class-type-6":1250000
},
{
"class-type-7":1250000
}
]
}
},
{
"edge-id":167772930,
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0002",
"local-vertex-id":2,
"remote-vertex-id":3,
"metric":10,
"edge-attributes":{
"local-address":"10.0.3.2",
"remote-address":"10.0.3.3",
"max-link-bandwidth":1250000,
"max-resv-link-bandwidth":1250000,
"unreserved-bandwidth":[
{
"class-type-0":1250000
},
{
"class-type-1":1250000
},
{
"class-type-2":1250000
},
{
"class-type-3":1250000
},
{
"class-type-4":1250000
},
{
"class-type-5":1250000
},
{
"class-type-6":1250000
},
{
"class-type-7":1250000
}
]
}
},
{
"edge-id":167772931,
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0003",
"local-vertex-id":3,
"remote-vertex-id":2,
"metric":10,
"edge-attributes":{
"admin-group":32,
"local-address":"10.0.3.3",
"remote-address":"10.0.3.2",
"max-link-bandwidth":1250000,
"max-resv-link-bandwidth":1250000,
"unreserved-bandwidth":[
{
"class-type-0":1250000
},
{
"class-type-1":1250000
},
{
"class-type-2":1250000
},
{
"class-type-3":1250000
},
{
"class-type-4":1250000
},
{
"class-type-5":1250000
},
{
"class-type-6":1250000
},
{
"class-type-7":1250000
}
]
}
},
{
"edge-id":167773186,
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0002",
"local-vertex-id":2,
"remote-vertex-id":4,
"metric":10,
"edge-attributes":{
"te-metric":30,
"local-address":"10.0.4.2",
"remote-address":"10.0.4.4",
"max-link-bandwidth":99999997952,
"max-resv-link-bandwidth":1250000,
"unreserved-bandwidth":[
{
"class-type-0":1250000
},
{
"class-type-1":1250000
},
{
"class-type-2":1250000
},
{
"class-type-3":1250000
},
{
"class-type-4":1250000
},
{
"class-type-5":1250000
},
{
"class-type-6":1250000
},
{
"class-type-7":1250000
}
],
"delay":25000
}
},
{
"edge-id":167773188,
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0004",
"local-vertex-id":4,
"remote-vertex-id":2,
"metric":10,
"edge-attributes":{
"local-address":"10.0.4.4",
"remote-address":"10.0.4.2",
"max-link-bandwidth":1250000,
"max-resv-link-bandwidth":1250000,
"unreserved-bandwidth":[
{
"class-type-0":1250000
},
{
"class-type-1":1250000
},
{
"class-type-2":1250000
},
{
"class-type-3":1250000
},
{
"class-type-4":1250000
},
{
"class-type-5":1250000
},
{
"class-type-6":1250000
},
{
"class-type-7":1250000
}
],
"delay":20000,
"jitter":10000
},
"segment-routing":[
{
"adj-sid":5000,
"flags":"0x30",
"weight":0
}
]
}
],
"subnets":[
{
"subnet-id":"10.0.0.1\/24",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0001",
"vertex-id":1,
"metric":10
},
{
"subnet-id":"10.0.0.2\/24",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0002",
"vertex-id":2,
"metric":10
},
{
"subnet-id":"10.0.1.1\/24",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0001",
"vertex-id":1,
"metric":10
},
{
"subnet-id":"10.0.1.2\/24",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0002",
"vertex-id":2,
"metric":10
},
{
"subnet-id":"10.0.3.2\/24",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0002",
"vertex-id":2,
"metric":10
},
{
"subnet-id":"10.0.3.3\/24",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0003",
"vertex-id":3,
"metric":10
},
{
"subnet-id":"10.0.4.2\/24",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0002",
"vertex-id":2,
"metric":10
},
{
"subnet-id":"10.0.4.4\/24",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0004",
"vertex-id":4,
"metric":10
},
{
"subnet-id":"10.0.255.1\/32",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0001",
"vertex-id":1,
"metric":10
},
{
"subnet-id":"10.0.255.2\/32",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0002",
"vertex-id":2,
"metric":10
},
{
"subnet-id":"10.0.255.3\/32",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0003",
"vertex-id":3,
"metric":10
},
{
"subnet-id":"10.0.255.4\/32",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0004",
"vertex-id":4,
"metric":10,
"segment-routing":{
"pref-sid":400,
"algo":0,
"flags":"0x60"
}
},
{
"subnet-id":"2001:db8::1\/64",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0001",
"vertex-id":1,
"metric":10
},
{
"subnet-id":"2001:db8::2\/64",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0002",
"vertex-id":2,
"metric":10
},
{
"subnet-id":"2001:db8:1::1:1\/64",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0001",
"vertex-id":1,
"metric":10
},
{
"subnet-id":"2001:db8:1::1:2\/64",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0002",
"vertex-id":2,
"metric":10
},
{
"subnet-id":"2001:db8:3::3:2\/64",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0002",
"vertex-id":2,
"metric":10
},
{
"subnet-id":"2001:db8:3::3:3\/64",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0003",
"vertex-id":3,
"metric":10
},
{
"subnet-id":"2001:db8:5::3:4\/64",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0004",
"vertex-id":4,
"metric":10
},
{
"subnet-id":"2001:db8:5::4:3\/64",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0003",
"vertex-id":3,
"metric":10
},
{
"subnet-id":"2001:db8:ffff::1\/128",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0001",
"vertex-id":1,
"metric":10
},
{
"subnet-id":"2001:db8:ffff::2\/128",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0002",
"vertex-id":2,
"metric":10
},
{
"subnet-id":"2001:db8:ffff::3\/128",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0003",
"vertex-id":3,
"metric":10
},
{
"subnet-id":"2001:db8:ffff::4\/128",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0004",
"vertex-id":4,
"metric":10,
"segment-routing":{
"pref-sid":1400,
"algo":0,
"flags":"0x60"
}
}
]
}
}

View File

@ -0,0 +1,971 @@
{
"ted":{
"name":"ISIS",
"key":1,
"verticesCount":4,
"edgesCount":16,
"subnetsCount":24,
"vertices":[
{
"vertex-id":1,
"status":"Sync",
"origin":"ISIS_L2",
"name":"r1",
"router-id":"10.0.255.1"
},
{
"vertex-id":2,
"status":"Sync",
"origin":"ISIS_L2",
"name":"r2",
"router-id":"10.0.255.2"
},
{
"vertex-id":3,
"status":"Sync",
"origin":"ISIS_L2",
"name":"r3",
"router-id":"10.0.255.3",
"router-id-v6":"2001:db8:1000::3"
},
{
"vertex-id":4,
"status":"Sync",
"origin":"ISIS_L2",
"name":"r4",
"router-id":"10.0.255.4",
"segment-routing":{
"srgb-size":10000,
"srgb-lower":10000,
"algorithms":[
{
"0":"SPF"
}
],
"srlb-size":1000,
"srlb-lower":5000,
"msd":12
}
}
],
"edges":[
{
"edge-id":1,
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0001",
"local-vertex-id":1,
"remote-vertex-id":2,
"metric":10,
"edge-attributes":{
"te-metric":20,
"extAdminGroup":{
"words":[
"0x80000001",
"0x00000001",
"0x00000000",
"0x00000000",
"0x00000001"
],
"bitPositions":[
0,
31,
32,
128
]
},
"local-address-v6":"2001:db8::1",
"remote-address-v6":"2001:db8::2",
"max-link-bandwidth":99999997952,
"max-resv-link-bandwidth":1250000,
"unreserved-bandwidth":[
{
"class-type-0":1250000
},
{
"class-type-1":1250000
},
{
"class-type-2":1250000
},
{
"class-type-3":1250000
},
{
"class-type-4":1250000
},
{
"class-type-5":1250000
},
{
"class-type-6":1250000
},
{
"class-type-7":1250000
}
],
"delay":10000,
"available-bandwidth":125000000.0
}
},
{
"edge-id":2,
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0002",
"local-vertex-id":2,
"remote-vertex-id":1,
"metric":10,
"edge-attributes":{
"local-address-v6":"2001:db8::2",
"max-link-bandwidth":1250000,
"max-resv-link-bandwidth":1250000,
"unreserved-bandwidth":[
{
"class-type-0":1250000
},
{
"class-type-1":1250000
},
{
"class-type-2":1250000
},
{
"class-type-3":1250000
},
{
"class-type-4":1250000
},
{
"class-type-5":1250000
},
{
"class-type-6":1250000
},
{
"class-type-7":1250000
}
]
}
},
{
"edge-id":65537,
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0001",
"local-vertex-id":1,
"remote-vertex-id":2,
"metric":10,
"edge-attributes":{
"local-address-v6":"2001:db8:1::1:1",
"remote-address-v6":"2001:db8:1::1:2",
"max-link-bandwidth":1250000,
"max-resv-link-bandwidth":1250000,
"unreserved-bandwidth":[
{
"class-type-0":1250000
},
{
"class-type-1":1250000
},
{
"class-type-2":1250000
},
{
"class-type-3":1250000
},
{
"class-type-4":1250000
},
{
"class-type-5":1250000
},
{
"class-type-6":1250000
},
{
"class-type-7":1250000
}
]
}
},
{
"edge-id":65538,
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0002",
"local-vertex-id":2,
"remote-vertex-id":1,
"metric":10,
"edge-attributes":{
"local-address-v6":"2001:db8:1::1:2",
"remote-address-v6":"2001:db8:1::1:1",
"max-link-bandwidth":1250000,
"max-resv-link-bandwidth":1250000,
"unreserved-bandwidth":[
{
"class-type-0":1250000
},
{
"class-type-1":1250000
},
{
"class-type-2":1250000
},
{
"class-type-3":1250000
},
{
"class-type-4":1250000
},
{
"class-type-5":1250000
},
{
"class-type-6":1250000
},
{
"class-type-7":1250000
}
]
}
},
{
"edge-id":196610,
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0002",
"local-vertex-id":2,
"remote-vertex-id":3,
"metric":10,
"edge-attributes":{
"local-address-v6":"2001:db8:3::3:2",
"remote-address-v6":"2001:db8:3::3:3",
"max-link-bandwidth":1250000,
"max-resv-link-bandwidth":1250000,
"unreserved-bandwidth":[
{
"class-type-0":1250000
},
{
"class-type-1":1250000
},
{
"class-type-2":1250000
},
{
"class-type-3":1250000
},
{
"class-type-4":1250000
},
{
"class-type-5":1250000
},
{
"class-type-6":1250000
},
{
"class-type-7":1250000
}
]
}
},
{
"edge-id":196611,
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0003",
"local-vertex-id":3,
"remote-vertex-id":2,
"metric":10,
"edge-attributes":{
"admin-group":32,
"local-address-v6":"2001:db8:3::3:3",
"remote-address-v6":"2001:db8:3::3:2",
"max-link-bandwidth":1250000,
"max-resv-link-bandwidth":1250000,
"unreserved-bandwidth":[
{
"class-type-0":1250000
},
{
"class-type-1":1250000
},
{
"class-type-2":1250000
},
{
"class-type-3":1250000
},
{
"class-type-4":1250000
},
{
"class-type-5":1250000
},
{
"class-type-6":1250000
},
{
"class-type-7":1250000
}
]
}
},
{
"edge-id":196612,
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0004",
"local-vertex-id":4,
"remote-vertex-id":3,
"metric":10,
"edge-attributes":{
"local-address-v6":"2001:db8:5::3:4",
"remote-address-v6":"2001:db8:5::4:3",
"max-link-bandwidth":1250000,
"max-resv-link-bandwidth":1250000,
"unreserved-bandwidth":[
{
"class-type-0":1250000
},
{
"class-type-1":1250000
},
{
"class-type-2":1250000
},
{
"class-type-3":1250000
},
{
"class-type-4":1250000
},
{
"class-type-5":1250000
},
{
"class-type-6":1250000
},
{
"class-type-7":1250000
}
]
},
"segment-routing":[
{
"adj-sid":5001,
"flags":"0xb0",
"weight":0
}
]
},
{
"edge-id":262147,
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0003",
"local-vertex-id":3,
"remote-vertex-id":4,
"metric":10,
"edge-attributes":{
"te-metric":10,
"local-address-v6":"2001:db8:5::4:3",
"remote-address-v6":"2001:db8:5::3:4",
"max-link-bandwidth":1250000,
"max-resv-link-bandwidth":1250000,
"unreserved-bandwidth":[
{
"class-type-0":1250000
},
{
"class-type-1":1250000
},
{
"class-type-2":1250000
},
{
"class-type-3":1250000
},
{
"class-type-4":1250000
},
{
"class-type-5":1250000
},
{
"class-type-6":1250000
},
{
"class-type-7":1250000
}
],
"delay":50000
}
},
{
"edge-id":167772161,
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0001",
"local-vertex-id":1,
"remote-vertex-id":2,
"metric":10,
"edge-attributes":{
"te-metric":20,
"extAdminGroup":{
"words":[
"0x80000001",
"0x00000001",
"0x00000000",
"0x00000000",
"0x00000001"
],
"bitPositions":[
0,
31,
32,
128
]
},
"local-address":"10.0.0.1",
"remote-address":"10.0.0.2",
"max-link-bandwidth":99999997952,
"max-resv-link-bandwidth":1250000,
"unreserved-bandwidth":[
{
"class-type-0":1250000
},
{
"class-type-1":1250000
},
{
"class-type-2":1250000
},
{
"class-type-3":1250000
},
{
"class-type-4":1250000
},
{
"class-type-5":1250000
},
{
"class-type-6":1250000
},
{
"class-type-7":1250000
}
],
"delay":10000,
"available-bandwidth":125000000.0
}
},
{
"edge-id":167772162,
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0002",
"local-vertex-id":2,
"remote-vertex-id":1,
"metric":10,
"edge-attributes":{
"local-address":"10.0.0.2",
"remote-address":"10.0.0.1",
"max-link-bandwidth":1250000,
"max-resv-link-bandwidth":1250000,
"unreserved-bandwidth":[
{
"class-type-0":1250000
},
{
"class-type-1":1250000
},
{
"class-type-2":1250000
},
{
"class-type-3":1250000
},
{
"class-type-4":1250000
},
{
"class-type-5":1250000
},
{
"class-type-6":1250000
},
{
"class-type-7":1250000
}
]
}
},
{
"edge-id":167772417,
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0001",
"local-vertex-id":1,
"remote-vertex-id":2,
"metric":10,
"edge-attributes":{
"local-address":"10.0.1.1",
"remote-address":"10.0.1.2",
"max-link-bandwidth":1250000,
"max-resv-link-bandwidth":1250000,
"unreserved-bandwidth":[
{
"class-type-0":1250000
},
{
"class-type-1":1250000
},
{
"class-type-2":1250000
},
{
"class-type-3":1250000
},
{
"class-type-4":1250000
},
{
"class-type-5":1250000
},
{
"class-type-6":1250000
},
{
"class-type-7":1250000
}
]
}
},
{
"edge-id":167772418,
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0002",
"local-vertex-id":2,
"remote-vertex-id":1,
"metric":10,
"edge-attributes":{
"local-address":"10.0.1.2",
"remote-address":"10.0.1.1",
"max-link-bandwidth":1250000,
"max-resv-link-bandwidth":1250000,
"unreserved-bandwidth":[
{
"class-type-0":1250000
},
{
"class-type-1":1250000
},
{
"class-type-2":1250000
},
{
"class-type-3":1250000
},
{
"class-type-4":1250000
},
{
"class-type-5":1250000
},
{
"class-type-6":1250000
},
{
"class-type-7":1250000
}
]
}
},
{
"edge-id":167772930,
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0002",
"local-vertex-id":2,
"remote-vertex-id":3,
"metric":10,
"edge-attributes":{
"local-address":"10.0.3.2",
"remote-address":"10.0.3.3",
"max-link-bandwidth":1250000,
"max-resv-link-bandwidth":1250000,
"unreserved-bandwidth":[
{
"class-type-0":1250000
},
{
"class-type-1":1250000
},
{
"class-type-2":1250000
},
{
"class-type-3":1250000
},
{
"class-type-4":1250000
},
{
"class-type-5":1250000
},
{
"class-type-6":1250000
},
{
"class-type-7":1250000
}
]
}
},
{
"edge-id":167772931,
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0003",
"local-vertex-id":3,
"remote-vertex-id":2,
"metric":10,
"edge-attributes":{
"admin-group":32,
"local-address":"10.0.3.3",
"remote-address":"10.0.3.2",
"max-link-bandwidth":1250000,
"max-resv-link-bandwidth":1250000,
"unreserved-bandwidth":[
{
"class-type-0":1250000
},
{
"class-type-1":1250000
},
{
"class-type-2":1250000
},
{
"class-type-3":1250000
},
{
"class-type-4":1250000
},
{
"class-type-5":1250000
},
{
"class-type-6":1250000
},
{
"class-type-7":1250000
}
]
}
},
{
"edge-id":167773186,
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0002",
"local-vertex-id":2,
"remote-vertex-id":4,
"metric":10,
"edge-attributes":{
"te-metric":30,
"local-address":"10.0.4.2",
"remote-address":"10.0.4.4",
"max-link-bandwidth":99999997952,
"max-resv-link-bandwidth":1250000,
"unreserved-bandwidth":[
{
"class-type-0":1250000
},
{
"class-type-1":1250000
},
{
"class-type-2":1250000
},
{
"class-type-3":1250000
},
{
"class-type-4":1250000
},
{
"class-type-5":1250000
},
{
"class-type-6":1250000
},
{
"class-type-7":1250000
}
],
"delay":25000
}
},
{
"edge-id":167773188,
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0004",
"local-vertex-id":4,
"remote-vertex-id":2,
"metric":10,
"edge-attributes":{
"local-address":"10.0.4.4",
"remote-address":"10.0.4.2",
"max-link-bandwidth":1250000,
"max-resv-link-bandwidth":1250000,
"unreserved-bandwidth":[
{
"class-type-0":1250000
},
{
"class-type-1":1250000
},
{
"class-type-2":1250000
},
{
"class-type-3":1250000
},
{
"class-type-4":1250000
},
{
"class-type-5":1250000
},
{
"class-type-6":1250000
},
{
"class-type-7":1250000
}
],
"delay":20000,
"jitter":10000
},
"segment-routing":[
{
"adj-sid":5000,
"flags":"0x30",
"weight":0
}
]
}
],
"subnets":[
{
"subnet-id":"10.0.0.1\/24",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0001",
"vertex-id":1,
"metric":10
},
{
"subnet-id":"10.0.0.2\/24",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0002",
"vertex-id":2,
"metric":10
},
{
"subnet-id":"10.0.1.1\/24",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0001",
"vertex-id":1,
"metric":10
},
{
"subnet-id":"10.0.1.2\/24",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0002",
"vertex-id":2,
"metric":10
},
{
"subnet-id":"10.0.3.2\/24",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0002",
"vertex-id":2,
"metric":10
},
{
"subnet-id":"10.0.3.3\/24",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0003",
"vertex-id":3,
"metric":10
},
{
"subnet-id":"10.0.4.2\/24",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0002",
"vertex-id":2,
"metric":10
},
{
"subnet-id":"10.0.4.4\/24",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0004",
"vertex-id":4,
"metric":10
},
{
"subnet-id":"10.0.255.1\/32",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0001",
"vertex-id":1,
"metric":10
},
{
"subnet-id":"10.0.255.2\/32",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0002",
"vertex-id":2,
"metric":10
},
{
"subnet-id":"10.0.255.3\/32",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0003",
"vertex-id":3,
"metric":10
},
{
"subnet-id":"10.0.255.4\/32",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0004",
"vertex-id":4,
"metric":10,
"segment-routing":{
"pref-sid":400,
"algo":0,
"flags":"0x60"
}
},
{
"subnet-id":"2001:db8::1\/64",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0001",
"vertex-id":1,
"metric":10
},
{
"subnet-id":"2001:db8::2\/64",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0002",
"vertex-id":2,
"metric":10
},
{
"subnet-id":"2001:db8:1::1:1\/64",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0001",
"vertex-id":1,
"metric":10
},
{
"subnet-id":"2001:db8:1::1:2\/64",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0002",
"vertex-id":2,
"metric":10
},
{
"subnet-id":"2001:db8:3::3:2\/64",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0002",
"vertex-id":2,
"metric":10
},
{
"subnet-id":"2001:db8:3::3:3\/64",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0003",
"vertex-id":3,
"metric":10
},
{
"subnet-id":"2001:db8:5::3:4\/64",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0004",
"vertex-id":4,
"metric":10
},
{
"subnet-id":"2001:db8:5::4:3\/64",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0003",
"vertex-id":3,
"metric":10
},
{
"subnet-id":"2001:db8:ffff::1\/128",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0001",
"vertex-id":1,
"metric":10
},
{
"subnet-id":"2001:db8:ffff::2\/128",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0002",
"vertex-id":2,
"metric":10
},
{
"subnet-id":"2001:db8:ffff::3\/128",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0003",
"vertex-id":3,
"metric":10
},
{
"subnet-id":"2001:db8:ffff::4\/128",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0004",
"vertex-id":4,
"metric":10,
"segment-routing":{
"pref-sid":1400,
"algo":0,
"flags":"0x60"
}
}
]
}
}

View File

@ -0,0 +1,971 @@
{
"ted":{
"name":"ISIS",
"key":1,
"verticesCount":4,
"edgesCount":16,
"subnetsCount":24,
"vertices":[
{
"vertex-id":1,
"status":"Sync",
"origin":"ISIS_L2",
"name":"r1",
"router-id":"10.0.255.1"
},
{
"vertex-id":2,
"status":"Sync",
"origin":"ISIS_L2",
"name":"r2",
"router-id":"10.0.255.2"
},
{
"vertex-id":3,
"status":"Sync",
"origin":"ISIS_L2",
"name":"r3",
"router-id":"10.0.255.3",
"router-id-v6":"2001:db8:1000::3"
},
{
"vertex-id":4,
"status":"Sync",
"origin":"ISIS_L2",
"name":"r4",
"router-id":"10.0.255.4",
"segment-routing":{
"srgb-size":10000,
"srgb-lower":10000,
"algorithms":[
{
"0":"SPF"
}
],
"srlb-size":1000,
"srlb-lower":5000,
"msd":12
}
}
],
"edges":[
{
"edge-id":1,
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0001",
"local-vertex-id":1,
"remote-vertex-id":2,
"metric":10,
"edge-attributes":{
"te-metric":20,
"extAdminGroup":{
"words":[
"0x80000001",
"0x00000002",
"0x00000000",
"0x00000000",
"0x00000001"
],
"bitPositions":[
0,
31,
33,
128
]
},
"local-address-v6":"2001:db8::1",
"remote-address-v6":"2001:db8::2",
"max-link-bandwidth":99999997952,
"max-resv-link-bandwidth":1250000,
"unreserved-bandwidth":[
{
"class-type-0":1250000
},
{
"class-type-1":1250000
},
{
"class-type-2":1250000
},
{
"class-type-3":1250000
},
{
"class-type-4":1250000
},
{
"class-type-5":1250000
},
{
"class-type-6":1250000
},
{
"class-type-7":1250000
}
],
"delay":10000,
"available-bandwidth":125000000.0
}
},
{
"edge-id":2,
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0002",
"local-vertex-id":2,
"remote-vertex-id":1,
"metric":10,
"edge-attributes":{
"local-address-v6":"2001:db8::2",
"max-link-bandwidth":1250000,
"max-resv-link-bandwidth":1250000,
"unreserved-bandwidth":[
{
"class-type-0":1250000
},
{
"class-type-1":1250000
},
{
"class-type-2":1250000
},
{
"class-type-3":1250000
},
{
"class-type-4":1250000
},
{
"class-type-5":1250000
},
{
"class-type-6":1250000
},
{
"class-type-7":1250000
}
]
}
},
{
"edge-id":65537,
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0001",
"local-vertex-id":1,
"remote-vertex-id":2,
"metric":10,
"edge-attributes":{
"local-address-v6":"2001:db8:1::1:1",
"remote-address-v6":"2001:db8:1::1:2",
"max-link-bandwidth":1250000,
"max-resv-link-bandwidth":1250000,
"unreserved-bandwidth":[
{
"class-type-0":1250000
},
{
"class-type-1":1250000
},
{
"class-type-2":1250000
},
{
"class-type-3":1250000
},
{
"class-type-4":1250000
},
{
"class-type-5":1250000
},
{
"class-type-6":1250000
},
{
"class-type-7":1250000
}
]
}
},
{
"edge-id":65538,
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0002",
"local-vertex-id":2,
"remote-vertex-id":1,
"metric":10,
"edge-attributes":{
"local-address-v6":"2001:db8:1::1:2",
"remote-address-v6":"2001:db8:1::1:1",
"max-link-bandwidth":1250000,
"max-resv-link-bandwidth":1250000,
"unreserved-bandwidth":[
{
"class-type-0":1250000
},
{
"class-type-1":1250000
},
{
"class-type-2":1250000
},
{
"class-type-3":1250000
},
{
"class-type-4":1250000
},
{
"class-type-5":1250000
},
{
"class-type-6":1250000
},
{
"class-type-7":1250000
}
]
}
},
{
"edge-id":196610,
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0002",
"local-vertex-id":2,
"remote-vertex-id":3,
"metric":10,
"edge-attributes":{
"local-address-v6":"2001:db8:3::3:2",
"remote-address-v6":"2001:db8:3::3:3",
"max-link-bandwidth":1250000,
"max-resv-link-bandwidth":1250000,
"unreserved-bandwidth":[
{
"class-type-0":1250000
},
{
"class-type-1":1250000
},
{
"class-type-2":1250000
},
{
"class-type-3":1250000
},
{
"class-type-4":1250000
},
{
"class-type-5":1250000
},
{
"class-type-6":1250000
},
{
"class-type-7":1250000
}
]
}
},
{
"edge-id":196611,
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0003",
"local-vertex-id":3,
"remote-vertex-id":2,
"metric":10,
"edge-attributes":{
"admin-group":32,
"local-address-v6":"2001:db8:3::3:3",
"remote-address-v6":"2001:db8:3::3:2",
"max-link-bandwidth":1250000,
"max-resv-link-bandwidth":1250000,
"unreserved-bandwidth":[
{
"class-type-0":1250000
},
{
"class-type-1":1250000
},
{
"class-type-2":1250000
},
{
"class-type-3":1250000
},
{
"class-type-4":1250000
},
{
"class-type-5":1250000
},
{
"class-type-6":1250000
},
{
"class-type-7":1250000
}
]
}
},
{
"edge-id":196612,
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0004",
"local-vertex-id":4,
"remote-vertex-id":3,
"metric":10,
"edge-attributes":{
"local-address-v6":"2001:db8:5::3:4",
"remote-address-v6":"2001:db8:5::4:3",
"max-link-bandwidth":1250000,
"max-resv-link-bandwidth":1250000,
"unreserved-bandwidth":[
{
"class-type-0":1250000
},
{
"class-type-1":1250000
},
{
"class-type-2":1250000
},
{
"class-type-3":1250000
},
{
"class-type-4":1250000
},
{
"class-type-5":1250000
},
{
"class-type-6":1250000
},
{
"class-type-7":1250000
}
]
},
"segment-routing":[
{
"adj-sid":5001,
"flags":"0xb0",
"weight":0
}
]
},
{
"edge-id":262147,
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0003",
"local-vertex-id":3,
"remote-vertex-id":4,
"metric":10,
"edge-attributes":{
"te-metric":10,
"local-address-v6":"2001:db8:5::4:3",
"remote-address-v6":"2001:db8:5::3:4",
"max-link-bandwidth":1250000,
"max-resv-link-bandwidth":1250000,
"unreserved-bandwidth":[
{
"class-type-0":1250000
},
{
"class-type-1":1250000
},
{
"class-type-2":1250000
},
{
"class-type-3":1250000
},
{
"class-type-4":1250000
},
{
"class-type-5":1250000
},
{
"class-type-6":1250000
},
{
"class-type-7":1250000
}
],
"delay":50000
}
},
{
"edge-id":167772161,
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0001",
"local-vertex-id":1,
"remote-vertex-id":2,
"metric":10,
"edge-attributes":{
"te-metric":20,
"extAdminGroup":{
"words":[
"0x80000001",
"0x00000002",
"0x00000000",
"0x00000000",
"0x00000001"
],
"bitPositions":[
0,
31,
33,
128
]
},
"local-address":"10.0.0.1",
"remote-address":"10.0.0.2",
"max-link-bandwidth":99999997952,
"max-resv-link-bandwidth":1250000,
"unreserved-bandwidth":[
{
"class-type-0":1250000
},
{
"class-type-1":1250000
},
{
"class-type-2":1250000
},
{
"class-type-3":1250000
},
{
"class-type-4":1250000
},
{
"class-type-5":1250000
},
{
"class-type-6":1250000
},
{
"class-type-7":1250000
}
],
"delay":10000,
"available-bandwidth":125000000.0
}
},
{
"edge-id":167772162,
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0002",
"local-vertex-id":2,
"remote-vertex-id":1,
"metric":10,
"edge-attributes":{
"local-address":"10.0.0.2",
"remote-address":"10.0.0.1",
"max-link-bandwidth":1250000,
"max-resv-link-bandwidth":1250000,
"unreserved-bandwidth":[
{
"class-type-0":1250000
},
{
"class-type-1":1250000
},
{
"class-type-2":1250000
},
{
"class-type-3":1250000
},
{
"class-type-4":1250000
},
{
"class-type-5":1250000
},
{
"class-type-6":1250000
},
{
"class-type-7":1250000
}
]
}
},
{
"edge-id":167772417,
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0001",
"local-vertex-id":1,
"remote-vertex-id":2,
"metric":10,
"edge-attributes":{
"local-address":"10.0.1.1",
"remote-address":"10.0.1.2",
"max-link-bandwidth":1250000,
"max-resv-link-bandwidth":1250000,
"unreserved-bandwidth":[
{
"class-type-0":1250000
},
{
"class-type-1":1250000
},
{
"class-type-2":1250000
},
{
"class-type-3":1250000
},
{
"class-type-4":1250000
},
{
"class-type-5":1250000
},
{
"class-type-6":1250000
},
{
"class-type-7":1250000
}
]
}
},
{
"edge-id":167772418,
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0002",
"local-vertex-id":2,
"remote-vertex-id":1,
"metric":10,
"edge-attributes":{
"local-address":"10.0.1.2",
"remote-address":"10.0.1.1",
"max-link-bandwidth":1250000,
"max-resv-link-bandwidth":1250000,
"unreserved-bandwidth":[
{
"class-type-0":1250000
},
{
"class-type-1":1250000
},
{
"class-type-2":1250000
},
{
"class-type-3":1250000
},
{
"class-type-4":1250000
},
{
"class-type-5":1250000
},
{
"class-type-6":1250000
},
{
"class-type-7":1250000
}
]
}
},
{
"edge-id":167772930,
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0002",
"local-vertex-id":2,
"remote-vertex-id":3,
"metric":10,
"edge-attributes":{
"local-address":"10.0.3.2",
"remote-address":"10.0.3.3",
"max-link-bandwidth":1250000,
"max-resv-link-bandwidth":1250000,
"unreserved-bandwidth":[
{
"class-type-0":1250000
},
{
"class-type-1":1250000
},
{
"class-type-2":1250000
},
{
"class-type-3":1250000
},
{
"class-type-4":1250000
},
{
"class-type-5":1250000
},
{
"class-type-6":1250000
},
{
"class-type-7":1250000
}
]
}
},
{
"edge-id":167772931,
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0003",
"local-vertex-id":3,
"remote-vertex-id":2,
"metric":10,
"edge-attributes":{
"admin-group":32,
"local-address":"10.0.3.3",
"remote-address":"10.0.3.2",
"max-link-bandwidth":1250000,
"max-resv-link-bandwidth":1250000,
"unreserved-bandwidth":[
{
"class-type-0":1250000
},
{
"class-type-1":1250000
},
{
"class-type-2":1250000
},
{
"class-type-3":1250000
},
{
"class-type-4":1250000
},
{
"class-type-5":1250000
},
{
"class-type-6":1250000
},
{
"class-type-7":1250000
}
]
}
},
{
"edge-id":167773186,
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0002",
"local-vertex-id":2,
"remote-vertex-id":4,
"metric":10,
"edge-attributes":{
"te-metric":30,
"local-address":"10.0.4.2",
"remote-address":"10.0.4.4",
"max-link-bandwidth":99999997952,
"max-resv-link-bandwidth":1250000,
"unreserved-bandwidth":[
{
"class-type-0":1250000
},
{
"class-type-1":1250000
},
{
"class-type-2":1250000
},
{
"class-type-3":1250000
},
{
"class-type-4":1250000
},
{
"class-type-5":1250000
},
{
"class-type-6":1250000
},
{
"class-type-7":1250000
}
],
"delay":25000
}
},
{
"edge-id":167773188,
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0004",
"local-vertex-id":4,
"remote-vertex-id":2,
"metric":10,
"edge-attributes":{
"local-address":"10.0.4.4",
"remote-address":"10.0.4.2",
"max-link-bandwidth":1250000,
"max-resv-link-bandwidth":1250000,
"unreserved-bandwidth":[
{
"class-type-0":1250000
},
{
"class-type-1":1250000
},
{
"class-type-2":1250000
},
{
"class-type-3":1250000
},
{
"class-type-4":1250000
},
{
"class-type-5":1250000
},
{
"class-type-6":1250000
},
{
"class-type-7":1250000
}
],
"delay":20000,
"jitter":10000
},
"segment-routing":[
{
"adj-sid":5000,
"flags":"0x30",
"weight":0
}
]
}
],
"subnets":[
{
"subnet-id":"10.0.0.1\/24",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0001",
"vertex-id":1,
"metric":10
},
{
"subnet-id":"10.0.0.2\/24",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0002",
"vertex-id":2,
"metric":10
},
{
"subnet-id":"10.0.1.1\/24",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0001",
"vertex-id":1,
"metric":10
},
{
"subnet-id":"10.0.1.2\/24",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0002",
"vertex-id":2,
"metric":10
},
{
"subnet-id":"10.0.3.2\/24",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0002",
"vertex-id":2,
"metric":10
},
{
"subnet-id":"10.0.3.3\/24",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0003",
"vertex-id":3,
"metric":10
},
{
"subnet-id":"10.0.4.2\/24",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0002",
"vertex-id":2,
"metric":10
},
{
"subnet-id":"10.0.4.4\/24",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0004",
"vertex-id":4,
"metric":10
},
{
"subnet-id":"10.0.255.1\/32",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0001",
"vertex-id":1,
"metric":10
},
{
"subnet-id":"10.0.255.2\/32",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0002",
"vertex-id":2,
"metric":10
},
{
"subnet-id":"10.0.255.3\/32",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0003",
"vertex-id":3,
"metric":10
},
{
"subnet-id":"10.0.255.4\/32",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0004",
"vertex-id":4,
"metric":10,
"segment-routing":{
"pref-sid":400,
"algo":0,
"flags":"0x60"
}
},
{
"subnet-id":"2001:db8::1\/64",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0001",
"vertex-id":1,
"metric":10
},
{
"subnet-id":"2001:db8::2\/64",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0002",
"vertex-id":2,
"metric":10
},
{
"subnet-id":"2001:db8:1::1:1\/64",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0001",
"vertex-id":1,
"metric":10
},
{
"subnet-id":"2001:db8:1::1:2\/64",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0002",
"vertex-id":2,
"metric":10
},
{
"subnet-id":"2001:db8:3::3:2\/64",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0002",
"vertex-id":2,
"metric":10
},
{
"subnet-id":"2001:db8:3::3:3\/64",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0003",
"vertex-id":3,
"metric":10
},
{
"subnet-id":"2001:db8:5::3:4\/64",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0004",
"vertex-id":4,
"metric":10
},
{
"subnet-id":"2001:db8:5::4:3\/64",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0003",
"vertex-id":3,
"metric":10
},
{
"subnet-id":"2001:db8:ffff::1\/128",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0001",
"vertex-id":1,
"metric":10
},
{
"subnet-id":"2001:db8:ffff::2\/128",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0002",
"vertex-id":2,
"metric":10
},
{
"subnet-id":"2001:db8:ffff::3\/128",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0003",
"vertex-id":3,
"metric":10
},
{
"subnet-id":"2001:db8:ffff::4\/128",
"status":"Sync",
"origin":"ISIS_L2",
"advertised-router":"0000.0000.0004",
"vertex-id":4,
"metric":10,
"segment-routing":{
"pref-sid":1400,
"algo":0,
"flags":"0x60"
}
}
]
}
}

View File

@ -0,0 +1 @@
ted_step8.json

View File

@ -250,6 +250,60 @@ def test_step6():
compare_ted_json_output(tgen, rname, "ted_step6.json")
def test_step7():
"Step7: Set extended admin-group on r1-eth0"
tgen = setup_testcase("Step7: Modify link parameters on r1")
tgen.net["r1"].cmd('vtysh -c "conf t" -c "affinity-map WHITE bit-position 0"')
tgen.net["r1"].cmd('vtysh -c "conf t" -c "affinity-map RED bit-position 31"')
tgen.net["r1"].cmd('vtysh -c "conf t" -c "affinity-map GREEN bit-position 32"')
tgen.net["r1"].cmd('vtysh -c "conf t" -c "affinity-map BLACK bit-position 128"')
tgen.net["r1"].cmd(
'vtysh -c "conf t" -c "interface r1-eth0" -c "link-params" -c "affinity RED WHITE BLACK GREEN"'
)
for rname in ["r1", "r2", "r3", "r4"]:
compare_ted_json_output(tgen, rname, "ted_step7.json")
def test_step8():
"Step8: Change value of affinity-map GREEN"
tgen = setup_testcase("Step8: Change value of affinity-map GREEN")
tgen.net["r1"].cmd('vtysh -c "conf t" -c "affinity-map GREEN bit-position 33"')
for rname in ["r1", "r2", "r3", "r4"]:
compare_ted_json_output(tgen, rname, "ted_step8.json")
def test_step9():
"Step9: Trying to remove affinity-map GREEN. \
Must not succeed because in use"
tgen = setup_testcase("Step9: Trying to remove affinity-map GREEN")
tgen.net["r1"].cmd('vtysh -c "conf t" -c "no affinity-map GREEN"')
for rname in ["r1", "r2", "r3", "r4"]:
compare_ted_json_output(tgen, rname, "ted_step9.json")
def test_step10():
"Step10: Removing r1-eth0 affinity GREEN"
tgen = setup_testcase("Step10: Removing r1-eth0 affinity GREEN")
tgen.net["r1"].cmd(
'vtysh -c "conf t" -c "interface r1-eth0" -c "link-params" -c "no affinity GREEN"'
)
for rname in ["r1", "r2", "r3", "r4"]:
compare_ted_json_output(tgen, rname, "ted_step10.json")
def test_memory_leak():
"Run the memory leak test and report results."

View File

@ -2216,6 +2216,29 @@ DEFUNSH(VTYSH_PATHD, pcep_cli_pcep_pce_config, pcep_cli_pcep_pce_config_cmd,
#endif /* HAVE_PATHD */
/* max value is EXT_ADMIN_GROUP_MAX_POSITIONS - 1 */
DEFUNSH(VTYSH_AFFMAP, affinity_map, vtysh_affinity_map_cmd,
"affinity-map NAME bit-position (0-1023)",
"Affinity map configuration\n"
"Affinity attribute name\n"
"Bit position for affinity attribute value\n"
"Bit position\n")
{
return CMD_SUCCESS;
}
/* max value is EXT_ADMIN_GROUP_MAX_POSITIONS - 1 */
DEFUNSH(VTYSH_AFFMAP, no_affinity_map, vtysh_no_affinity_map_cmd,
"no affinity-map NAME$name [bit-position (0-1023)$position]",
NO_STR
"Affinity map configuration\n"
"Affinity attribute name\n"
"Bit position for affinity attribute value\n"
"Bit position\n")
{
return CMD_SUCCESS;
}
DEFUNSH(VTYSH_RMAP, vtysh_route_map, vtysh_route_map_cmd,
"route-map RMAP_NAME <deny|permit> (1-65535)",
"Create route-map or enter route-map command mode\n"
@ -4850,6 +4873,9 @@ void vtysh_init_vty(void)
install_element(VRF_NODE, &vtysh_exit_vrf_cmd);
install_element(VRF_NODE, &vtysh_quit_vrf_cmd);
install_element(CONFIG_NODE, &vtysh_affinity_map_cmd);
install_element(CONFIG_NODE, &vtysh_no_affinity_map_cmd);
install_node(&rmap_node);
install_element(CONFIG_NODE, &vtysh_route_map_cmd);
install_element(RMAP_NODE, &vtysh_exit_rmap_cmd);

View File

@ -59,6 +59,7 @@ extern struct thread_master *master;
* things like prefix lists are not even initialised) */
#define VTYSH_ALL VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_LDPD|VTYSH_BGPD|VTYSH_ISISD|VTYSH_PIMD|VTYSH_PIM6D|VTYSH_NHRPD|VTYSH_EIGRPD|VTYSH_BABELD|VTYSH_SHARPD|VTYSH_PBRD|VTYSH_STATICD|VTYSH_BFDD|VTYSH_FABRICD|VTYSH_VRRPD|VTYSH_PATHD
#define VTYSH_ACL VTYSH_BFDD|VTYSH_BABELD|VTYSH_BGPD|VTYSH_EIGRPD|VTYSH_ISISD|VTYSH_FABRICD|VTYSH_LDPD|VTYSH_NHRPD|VTYSH_OSPF6D|VTYSH_OSPFD|VTYSH_PBRD|VTYSH_PIMD|VTYSH_PIM6D|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_VRRPD|VTYSH_ZEBRA
#define VTYSH_AFFMAP VTYSH_ZEBRA | VTYSH_ISISD
#define VTYSH_RMAP VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_BGPD|VTYSH_ISISD|VTYSH_PIMD|VTYSH_EIGRPD|VTYSH_FABRICD
#define VTYSH_INTERFACE_SUBSET \
VTYSH_ZEBRA | VTYSH_RIPD | VTYSH_RIPNGD | VTYSH_OSPFD | VTYSH_OSPF6D | \

View File

@ -395,6 +395,9 @@ void vtysh_config_parse_line(void *arg, const char *line)
else if (strncmp(line, "router openfabric", strlen("router openfabric"))
== 0)
config = config_get(OPENFABRIC_NODE, line);
else if (strncmp(line, "affinity-map",
strlen("affinity-map")) == 0)
config = config_get(AFFMAP_NODE, line);
else if (strncmp(line, "route-map", strlen("route-map")) == 0)
config = config_get(RMAP_NODE, line);
else if (strncmp(line, "no route-map", strlen("no route-map"))
@ -526,14 +529,15 @@ void vtysh_config_parse_line(void *arg, const char *line)
/* Macro to check delimiter is needed between each configuration line
* or not. */
#define NO_DELIMITER(I) \
((I) == ACCESS_NODE || (I) == PREFIX_NODE || (I) == IP_NODE \
|| (I) == AS_LIST_NODE || (I) == COMMUNITY_LIST_NODE \
|| (I) == COMMUNITY_ALIAS_NODE || (I) == ACCESS_IPV6_NODE \
|| (I) == ACCESS_MAC_NODE || (I) == PREFIX_IPV6_NODE \
|| (I) == FORWARDING_NODE || (I) == DEBUG_NODE || (I) == AAA_NODE \
|| (I) == VRF_DEBUG_NODE || (I) == NORTHBOUND_DEBUG_NODE \
|| (I) == RMAP_DEBUG_NODE || (I) == RESOLVER_DEBUG_NODE \
|| (I) == MPLS_NODE || (I) == KEYCHAIN_KEY_NODE)
((I) == AFFMAP_NODE || (I) == ACCESS_NODE || (I) == PREFIX_NODE || \
(I) == IP_NODE || (I) == AS_LIST_NODE || \
(I) == COMMUNITY_LIST_NODE || (I) == COMMUNITY_ALIAS_NODE || \
(I) == ACCESS_IPV6_NODE || (I) == ACCESS_MAC_NODE || \
(I) == PREFIX_IPV6_NODE || (I) == FORWARDING_NODE || \
(I) == DEBUG_NODE || (I) == AAA_NODE || (I) == VRF_DEBUG_NODE || \
(I) == NORTHBOUND_DEBUG_NODE || (I) == RMAP_DEBUG_NODE || \
(I) == RESOLVER_DEBUG_NODE || (I) == MPLS_NODE || \
(I) == KEYCHAIN_KEY_NODE)
static void configvec_dump(vector vec, bool nested)
{

View File

@ -0,0 +1,81 @@
module frr-affinity-map {
yang-version 1.1;
namespace "http://frrouting.org/yang/affinity-map";
prefix frr-affinity-map;
import ietf-inet-types {
prefix inet;
}
import frr-filter {
prefix filter;
}
import frr-interface {
prefix frr-interface;
}
organization
"FRRouting";
contact
"FRR Users List: <mailto:frog@lists.frrouting.org>
FRR Development List: <mailto:dev@lists.frrouting.org>";
description
"This module defines route map settings
Copyright 2022 FRRouting
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.";
revision 2022-11-03 {
description
"Initial revision";
}
container lib {
container affinity-maps {
description
"Affinity Mapping Table";
list affinity-map {
key "name";
description
"Affinity Mapping configuration";
leaf name {
type string {
length "1..32";
}
description
"Affinity Name";
}
leaf value {
type uint16 {
range "0..1023";
}
description
"Bit position";
}
}
}
}
}

View File

@ -11,6 +11,10 @@ module frr-zebra {
prefix inet;
}
import frr-affinity-map {
prefix frr-affinity-map;
}
import frr-route-map {
prefix frr-route-map;
}
@ -1985,7 +1989,55 @@ module frr-zebra {
description
"Link bandwidth informational parameter, in megabits.";
}
// TODO -- link-params for (experimental/partial TE use in IGP extensions)
container link-params {
description
"link-params for Traffic-Engineering (TE) use in IGP extensions.";
choice admin-group-mode {
description "Admin-group mode";
case legacy {
description
"Legacy mode. Only support standard admin-group (RFC3630/5305/5329)";
leaf legacy-admin-group {
description "Admin-Group value";
type uint32;
}
}
case affinity {
container affinities {
leaf-list affinity {
type string;
max-elements "256";
description
"Array of Attribute Names";
}
}
}
}
leaf affinity-mode {
description
"Affinity mode";
default "extended";
type enumeration {
enum extended {
value 0;
description
"Extended Admin-Group only (RFC7308)";
}
enum standard {
value 1;
description
"Standard Admin-Group only (RFC3630/5305/5329)";
}
enum both {
value 2;
description
"Standard and extended Admin-Group";
}
}
}
// TODO -- other link-params options
// for (experimental/partial TE use in IGP extensions)
}
container state {
config false;
description

View File

@ -19,6 +19,7 @@ EXTRA_DIST += yang/embedmodel.py
# global symbols :(. Just put it in the daemon. Dynamic libraries.so work
# without problems, as seen in libfrr.
dist_yangmodels_DATA += yang/frr-affinity-map.yang
dist_yangmodels_DATA += yang/frr-filter.yang
dist_yangmodels_DATA += yang/frr-module-translator.yang
dist_yangmodels_DATA += yang/frr-nexthop.yang

View File

@ -33,6 +33,7 @@
#include "log.h"
#include "zclient.h"
#include "vrf.h"
#include "lib/northbound_cli.h"
#include "zebra/rtadv.h"
#include "zebra_ns.h"
@ -3362,6 +3363,8 @@ DEFUN (no_link_params_enable,
NO_STR
"Disable link parameters on this interface\n")
{
char xpath[XPATH_MAXLEN];
int ret;
VTY_DECLVAR_CONTEXT(interface, ifp);
if (IS_ZEBRA_DEBUG_EVENT || IS_ZEBRA_DEBUG_MPLS)
@ -3370,6 +3373,18 @@ DEFUN (no_link_params_enable,
if_link_params_free(ifp);
snprintf(
xpath, sizeof(xpath),
"/frr-interface:lib/interface[name='%s']/frr-zebra:zebra/link-params/affinities",
ifp->name);
if (yang_dnode_exists(running_config->dnode, xpath))
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
ret = nb_cli_apply_changes(vty, NULL);
if (ret != CMD_SUCCESS)
return ret;
/* force protocols to update LINK STATE due to parameters change */
if (if_is_operative(ifp))
zebra_interface_parameters_update(ifp);
@ -3535,16 +3550,27 @@ DEFUN (link_params_unrsv_bw,
return CMD_SUCCESS;
}
DEFUN (link_params_admin_grp,
link_params_admin_grp_cmd,
"admin-grp BITPATTERN",
"Administrative group membership\n"
"32-bit Hexadecimal value (e.g. 0xa1)\n")
DEFPY_YANG(link_params_admin_grp, link_params_admin_grp_cmd,
"admin-grp BITPATTERN",
"Administrative group membership\n"
"32-bit Hexadecimal value (e.g. 0xa1)\n")
{
char xpath[XPATH_MAXLEN];
int idx_bitpattern = 1;
VTY_DECLVAR_CONTEXT(interface, ifp);
struct if_link_params *iflp = if_link_params_get(ifp);
unsigned long value;
char value_str[11];
VTY_DECLVAR_CONTEXT(interface, ifp);
snprintf(
xpath, sizeof(xpath),
"/frr-interface:lib/interface[name='%s']/frr-zebra:zebra/link-params/affinities",
ifp->name);
if (yang_dnode_exists(running_config->dnode, xpath)) {
vty_out(vty,
"cannot use the admin-grp command when affinity is set\n");
return CMD_WARNING_CONFIG_FAILED;
}
if (sscanf(argv[idx_bitpattern]->arg, "0x%lx", &value) != 1) {
vty_out(vty, "link_params_admin_grp: fscanf: %s\n",
@ -3552,27 +3578,29 @@ DEFUN (link_params_admin_grp,
return CMD_WARNING_CONFIG_FAILED;
}
if (!iflp)
iflp = if_link_params_enable(ifp);
if (value > 0xFFFFFFFF) {
vty_out(vty, "value must be not be superior to 0xFFFFFFFF\n");
return CMD_WARNING_CONFIG_FAILED;
}
/* Update Administrative Group if needed */
link_param_cmd_set_uint32(ifp, &iflp->admin_grp, LP_ADM_GRP, value);
snprintf(value_str, sizeof(value_str), "%ld", value);
return CMD_SUCCESS;
nb_cli_enqueue_change(
vty, "./frr-zebra:zebra/link-params/legacy-admin-group",
NB_OP_MODIFY, value_str);
return nb_cli_apply_changes(vty, NULL);
}
DEFUN (no_link_params_admin_grp,
no_link_params_admin_grp_cmd,
"no admin-grp",
NO_STR
"Disable Administrative group membership on this interface\n")
DEFPY_YANG(no_link_params_admin_grp, no_link_params_admin_grp_cmd,
"no admin-grp",
NO_STR "Disable Administrative group membership on this interface\n")
{
VTY_DECLVAR_CONTEXT(interface, ifp);
nb_cli_enqueue_change(
vty, "./frr-zebra:zebra/link-params/legacy-admin-group",
NB_OP_DESTROY, NULL);
/* Unset Admin Group */
link_param_cmd_unset(ifp, LP_ADM_GRP);
return CMD_SUCCESS;
return nb_cli_apply_changes(vty, NULL);
}
/* RFC5392 & RFC5316: INTER-AS */
@ -3989,6 +4017,118 @@ DEFUN (no_link_params_use_bw,
return CMD_SUCCESS;
}
static int ag_change(struct vty *vty, int argc, struct cmd_token **argv,
const char *xpath, bool no, int start_idx)
{
for (int i = start_idx; i < argc; i++)
nb_cli_enqueue_change(vty, xpath,
no ? NB_OP_DESTROY : NB_OP_CREATE,
argv[i]->arg);
return nb_cli_apply_changes(vty, NULL);
}
/*
* XPath:
* /frr-interface:lib/interface/frr-zebra:zebra/link-params/affinities/affinity
*/
DEFPY_YANG(link_params_affinity, link_params_affinity_cmd,
"[no] affinity NAME...",
NO_STR
"Interface affinities\n"
"Affinity names\n")
{
VTY_DECLVAR_CONTEXT(interface, ifp);
char xpath[XPATH_MAXLEN];
snprintf(
xpath, sizeof(xpath),
"/frr-interface:lib/interface[name='%s']/frr-zebra:zebra/link-params/legacy-admin-group",
ifp->name);
if (yang_dnode_exists(running_config->dnode, xpath)) {
vty_out(vty,
"cannot use the affinity command when admin-grp is set\n");
return CMD_WARNING_CONFIG_FAILED;
}
return ag_change(vty, argc, argv,
"./frr-zebra:zebra/link-params/affinities/affinity",
no, no ? 2 : 1);
}
/*
* XPath:
* /frr-interface:lib/interface/frr-zebra:zebra/link-params/affinities/affinity-mode
*/
DEFPY_YANG(link_params_affinity_mode, link_params_affinity_mode_cmd,
"affinity-mode <standard|extended|both>$affmode",
"Interface affinity mode\n"
"Standard Admin-Group only RFC3630,5305,5329 (default)\n"
"Extended Admin-Group only RFC7308\n"
"Standard and extended Admin-Group format\n")
{
const char *xpath = "./frr-zebra:zebra/link-params/affinity-mode";
nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, affmode);
return nb_cli_apply_changes(vty, NULL);
}
DEFPY_YANG(no_link_params_affinity_mode, no_link_params_affinity_mode_cmd,
"no affinity-mode [<standard|extended|both>]",
NO_STR
"Interface affinity mode\n"
"Standard Admin-Group only RFC3630,5305,5329 (default)\n"
"Extended Admin-Group only RFC7308\n"
"Standard and extended Admin-Group format\n")
{
const char *xpath = "./frr-zebra:zebra/link-params/affinity-mode";
nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, "standard");
return nb_cli_apply_changes(vty, NULL);
}
static int ag_iter_cb(const struct lyd_node *dnode, void *arg)
{
struct vty *vty = (struct vty *)arg;
vty_out(vty, " %s", yang_dnode_get_string(dnode, "."));
return YANG_ITER_CONTINUE;
}
void cli_show_legacy_admin_group(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
if (!yang_dnode_exists(dnode, "./legacy-admin-group"))
return;
vty_out(vty, " admin-group 0x%x\n",
yang_dnode_get_uint32(dnode, "./legacy-admin-group"));
}
void cli_show_affinity_mode(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
enum affinity_mode affinity_mode = yang_dnode_get_enum(dnode, ".");
if (affinity_mode == AFFINITY_MODE_STANDARD)
vty_out(vty, " affinity-mode standard\n");
else if (affinity_mode == AFFINITY_MODE_BOTH)
vty_out(vty, " affinity-mode both\n");
}
void cli_show_affinity(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
if (!yang_dnode_exists(dnode, "./affinity"))
return;
vty_out(vty, " affinity");
yang_dnode_iterate(ag_iter_cb, vty, dnode, "./affinity");
vty_out(vty, "\n");
}
int if_ip_address_install(struct interface *ifp, struct prefix *prefix,
const char *label, struct prefix *pp)
{
@ -4585,6 +4725,8 @@ DEFUN (no_ipv6_address,
static int link_params_config_write(struct vty *vty, struct interface *ifp)
{
const struct lyd_node *dnode;
char xpath[XPATH_MAXLEN];
int i;
if ((ifp == NULL) || !HAS_LINK_PARAMS(ifp))
@ -4607,8 +4749,15 @@ static int link_params_config_write(struct vty *vty, struct interface *ifp)
vty_out(vty, " unrsv-bw %d %g\n", i,
iflp->unrsv_bw[i]);
}
if (IS_PARAM_SET(iflp, LP_ADM_GRP))
vty_out(vty, " admin-grp 0x%x\n", iflp->admin_grp);
snprintf(
xpath, sizeof(xpath),
"/frr-interface:lib/interface[name='%s']/frr-zebra:zebra/link-params",
ifp->name);
dnode = yang_dnode_get(running_config->dnode, xpath);
if (dnode)
nb_cli_show_dnode_cmds(vty, dnode, false);
if (IS_PARAM_SET(iflp, LP_DELAY)) {
vty_out(vty, " delay %u", iflp->av_delay);
if (IS_PARAM_SET(iflp, LP_MM_DELAY)) {
@ -4630,6 +4779,7 @@ static int link_params_config_write(struct vty *vty, struct interface *ifp)
if (IS_PARAM_SET(iflp, LP_RMT_AS))
vty_out(vty, " neighbor %pI4 as %u\n", &iflp->rmt_ip,
iflp->rmt_as);
vty_out(vty, " exit-link-params\n");
return 0;
}
@ -4789,6 +4939,9 @@ void zebra_if_init(void)
install_element(LINK_PARAMS_NODE, &no_link_params_res_bw_cmd);
install_element(LINK_PARAMS_NODE, &link_params_use_bw_cmd);
install_element(LINK_PARAMS_NODE, &no_link_params_use_bw_cmd);
install_element(LINK_PARAMS_NODE, &link_params_affinity_cmd);
install_element(LINK_PARAMS_NODE, &link_params_affinity_mode_cmd);
install_element(LINK_PARAMS_NODE, &no_link_params_affinity_mode_cmd);
install_element(LINK_PARAMS_NODE, &exit_link_params_cmd);
/* setup EVPN MH elements */

View File

@ -303,6 +303,16 @@ extern void zebra_if_update_all_links(struct zebra_ns *zns);
*/
extern int zebra_if_update_protodown_rc(struct interface *ifp, bool new_down,
uint32_t new_protodown_rc);
extern void cli_show_legacy_admin_group(struct vty *vty,
const struct lyd_node *dnode,
bool show_defaults);
extern void cli_show_affinity_mode(struct vty *vty,
const struct lyd_node *dnode,
bool show_defaults);
extern void cli_show_affinity(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
/**
* Set protodown with single reason.
*/

View File

@ -33,6 +33,7 @@
#include "sigevent.h"
#include "vrf.h"
#include "libfrr.h"
#include "affinitymap.h"
#include "routemap.h"
#include "routing_nb.h"
@ -259,6 +260,7 @@ struct frr_signal_t zebra_signals[] = {
},
};
/* clang-format off */
static const struct frr_yang_module_info *const zebra_yang_modules[] = {
&frr_filter_info,
&frr_interface_info,
@ -266,8 +268,10 @@ static const struct frr_yang_module_info *const zebra_yang_modules[] = {
&frr_zebra_info,
&frr_vrf_info,
&frr_routing_info,
&frr_affinity_map_info,
&frr_zebra_route_map_info,
};
/* clang-format on */
FRR_DAEMON_INFO(
zebra, ZEBRA, .vty_port = ZEBRA_VTY_PORT, .flags = FRR_NO_ZCLIENT,

View File

@ -62,6 +62,7 @@ zebra_zebra_SOURCES = \
zebra/tc_netlink.c \
zebra/tc_socket.c \
zebra/zapi_msg.c \
zebra/zebra_affinitymap.c \
zebra/zebra_dplane.c \
zebra/zebra_errors.c \
zebra/zebra_gr.c \
@ -147,6 +148,7 @@ noinst_HEADERS += \
zebra/table_manager.h \
zebra/tc_netlink.h \
zebra/zapi_msg.h \
zebra/zebra_affinitymap.h \
zebra/zebra_dplane.h \
zebra/zebra_errors.h \
zebra/zebra_evpn.h \

144
zebra/zebra_affinitymap.c Normal file
View File

@ -0,0 +1,144 @@
/*
* zebra affinity-map.
*
* Copyright 2022 6WIND S.A.
*
* This file is part of Free Range Routing (FRR).
*
* FRR is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* FRR is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; see the file COPYING; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
#include "lib/if.h"
#include "lib/vrf.h"
#include "zebra/redistribute.h"
#include "zebra/zebra_affinitymap.h"
static bool zebra_affinity_map_check_use(const char *affmap_name)
{
char xpath[XPATH_MAXLEN];
struct interface *ifp;
struct vrf *vrf;
RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) {
FOR_ALL_INTERFACES (vrf, ifp) {
snprintf(xpath, sizeof(xpath),
"/frr-interface:lib/interface[name='%s']",
ifp->name);
if (!yang_dnode_exists(running_config->dnode, xpath))
continue;
snprintf(
xpath, sizeof(xpath),
"/frr-interface:lib/interface[name='%s']/frr-zebra:zebra/link-params/affinities[affinity='%s']",
ifp->name, affmap_name);
if (yang_dnode_exists(running_config->dnode, xpath))
return true;
}
}
return false;
}
static bool zebra_affinity_map_check_update(const char *affmap_name,
uint16_t new_pos)
{
char xpath[XPATH_MAXLEN];
struct interface *ifp;
struct vrf *vrf;
/* check whether the affinity-map new bit position is upper than 31
* but is used on an interface on which affinity-mode is standard.
* Return false if the change is not possible.
*/
if (new_pos < 32)
return true;
RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) {
FOR_ALL_INTERFACES (vrf, ifp) {
snprintf(xpath, sizeof(xpath),
"/frr-interface:lib/interface[name='%s']",
ifp->name);
if (!yang_dnode_exists(running_config->dnode, xpath))
continue;
snprintf(
xpath, sizeof(xpath),
"/frr-interface:lib/interface[name='%s']/frr-zebra:zebra/link-params/affinities[affinity='%s']",
ifp->name, affmap_name);
if (!yang_dnode_exists(running_config->dnode, xpath))
continue;
if (yang_dnode_get_enum(
running_config->dnode,
"/frr-interface:lib/interface[name='%s']/frr-zebra:zebra/link-params/affinity-mode",
ifp->name) == AFFINITY_MODE_STANDARD)
return false;
}
}
return true;
}
static void zebra_affinity_map_update(const char *affmap_name, uint16_t old_pos,
uint16_t new_pos)
{
struct if_link_params *iflp;
enum affinity_mode aff_mode;
char xpath[XPATH_MAXLEN];
struct interface *ifp;
struct vrf *vrf;
RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) {
FOR_ALL_INTERFACES (vrf, ifp) {
snprintf(xpath, sizeof(xpath),
"/frr-interface:lib/interface[name='%s']",
ifp->name);
if (!yang_dnode_exists(running_config->dnode, xpath))
continue;
snprintf(
xpath, sizeof(xpath),
"/frr-interface:lib/interface[name='%s']/frr-zebra:zebra/link-params/affinities[affinity='%s']",
ifp->name, affmap_name);
if (!yang_dnode_exists(running_config->dnode, xpath))
continue;
aff_mode = yang_dnode_get_enum(
running_config->dnode,
"/frr-interface:lib/interface[name='%s']/frr-zebra:zebra/link-params/affinity-mode",
ifp->name);
iflp = if_link_params_get(ifp);
if (aff_mode == AFFINITY_MODE_EXTENDED ||
aff_mode == AFFINITY_MODE_BOTH) {
admin_group_unset(&iflp->ext_admin_grp,
old_pos);
admin_group_set(&iflp->ext_admin_grp, new_pos);
}
if (aff_mode == AFFINITY_MODE_STANDARD ||
aff_mode == AFFINITY_MODE_BOTH) {
iflp->admin_grp &= ~(1 << old_pos);
if (new_pos < 32)
iflp->admin_grp |= 1 << new_pos;
if (iflp->admin_grp == 0)
UNSET_PARAM(iflp, LP_ADM_GRP);
}
if (if_is_operative(ifp))
zebra_interface_parameters_update(ifp);
}
}
}
void zebra_affinity_map_init(void)
{
affinity_map_init();
affinity_map_set_check_use_hook(zebra_affinity_map_check_use);
affinity_map_set_check_update_hook(zebra_affinity_map_check_update);
affinity_map_set_update_hook(zebra_affinity_map_update);
}

38
zebra/zebra_affinitymap.h Normal file
View File

@ -0,0 +1,38 @@
/*
* Zebra affinity-map header
*
* Copyright 2022 6WIND S.A.
*
* This file is part of Free Range Routing (FRR).
*
* FRR is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* FRR is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; see the file COPYING; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __ZEBRA_AFFINITYMAP_H__
#define __ZEBRA_AFFINITYMAP_H__
#include "lib/affinitymap.h"
#ifdef __cplusplus
extern "C" {
#endif
extern void zebra_affinity_map_init(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -18,6 +18,7 @@
*/
#include <zebra.h>
#include "interface.h"
#include "northbound.h"
#include "libfrr.h"
#include "zebra_nb.h"
@ -350,6 +351,41 @@ const struct frr_yang_module_info frr_zebra_info = {
.destroy = lib_interface_zebra_bandwidth_destroy,
}
},
{
.xpath = "/frr-interface:lib/interface/frr-zebra:zebra/bandwidth",
.cbs = {
.modify = lib_interface_zebra_bandwidth_modify,
.destroy = lib_interface_zebra_bandwidth_destroy,
}
},
{
.xpath = "/frr-interface:lib/interface/frr-zebra:zebra/link-params/legacy-admin-group",
.cbs = {
.modify = lib_interface_zebra_legacy_admin_group_modify,
.destroy = lib_interface_zebra_legacy_admin_group_destroy,
.cli_show = cli_show_legacy_admin_group,
},
},
{
.xpath = "/frr-interface:lib/interface/frr-zebra:zebra/link-params/affinities",
.cbs = {
.cli_show = cli_show_affinity,
},
},
{
.xpath = "/frr-interface:lib/interface/frr-zebra:zebra/link-params/affinities/affinity",
.cbs = {
.create = lib_interface_zebra_affinity_create,
.destroy = lib_interface_zebra_affinity_destroy,
},
},
{
.xpath = "/frr-interface:lib/interface/frr-zebra:zebra/link-params/affinity-mode",
.cbs = {
.modify = lib_interface_zebra_affinity_mode_modify,
.cli_show = cli_show_affinity_mode,
},
},
{
.xpath = "/frr-interface:lib/interface/frr-zebra:zebra/state/up-count",
.cbs = {

View File

@ -109,6 +109,13 @@ int lib_interface_zebra_shutdown_modify(struct nb_cb_modify_args *args);
int lib_interface_zebra_shutdown_destroy(struct nb_cb_destroy_args *args);
int lib_interface_zebra_bandwidth_modify(struct nb_cb_modify_args *args);
int lib_interface_zebra_bandwidth_destroy(struct nb_cb_destroy_args *args);
int lib_interface_zebra_legacy_admin_group_modify(
struct nb_cb_modify_args *args);
int lib_interface_zebra_legacy_admin_group_destroy(
struct nb_cb_destroy_args *args);
int lib_interface_zebra_affinity_create(struct nb_cb_create_args *args);
int lib_interface_zebra_affinity_destroy(struct nb_cb_destroy_args *args);
int lib_interface_zebra_affinity_mode_modify(struct nb_cb_modify_args *args);
struct yang_data *
lib_interface_zebra_state_up_count_get_elem(struct nb_cb_get_elem_args *args);
struct yang_data *

View File

@ -19,6 +19,8 @@
#include <zebra.h>
#include "lib/admin_group.h"
#include "lib/affinitymap.h"
#include "lib/log.h"
#include "lib/northbound.h"
#include "lib/printfrr.h"
@ -1139,6 +1141,275 @@ int lib_interface_zebra_bandwidth_destroy(struct nb_cb_destroy_args *args)
return NB_OK;
}
/*
* XPath:
* /frr-interface:lib/interface/frr-zebra:zebra/link-params/legacy-admin-group
*/
int lib_interface_zebra_legacy_admin_group_modify(
struct nb_cb_modify_args *args)
{
struct interface *ifp;
struct if_link_params *iflp;
uint32_t admin_group_value;
ifp = nb_running_get_entry(args->dnode, NULL, true);
admin_group_value = yang_dnode_get_uint32(args->dnode, ".");
if (!ifp)
return NB_ERR_RESOURCE;
iflp = if_link_params_get(ifp);
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
break;
case NB_EV_APPLY:
if (!iflp)
iflp = if_link_params_enable(ifp);
iflp->admin_grp = admin_group_value;
SET_PARAM(iflp, LP_ADM_GRP);
admin_group_clear(&iflp->ext_admin_grp);
UNSET_PARAM(iflp, LP_EXTEND_ADM_GRP);
if (if_is_operative(ifp))
zebra_interface_parameters_update(ifp);
break;
}
return NB_OK;
}
int lib_interface_zebra_legacy_admin_group_destroy(
struct nb_cb_destroy_args *args)
{
struct interface *ifp;
struct if_link_params *iflp;
ifp = nb_running_get_entry(args->dnode, NULL, true);
if (!ifp)
return NB_ERR_RESOURCE;
iflp = if_link_params_get(ifp);
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
break;
case NB_EV_APPLY:
if (!iflp)
iflp = if_link_params_enable(ifp);
iflp->admin_grp = 0;
UNSET_PARAM(iflp, LP_ADM_GRP);
if (if_is_operative(ifp))
zebra_interface_parameters_update(ifp);
break;
}
return NB_OK;
}
/*
* XPath:
* /frr-interface:lib/interface/frr-zebra:zebra/link-params/affinities/affinity
*/
int lib_interface_zebra_affinity_create(struct nb_cb_create_args *args)
{
struct interface *ifp;
const char *affname;
struct if_link_params *iflp;
struct affinity_map *affmap;
enum affinity_mode affinity_mode;
ifp = nb_running_get_entry(args->dnode, NULL, true);
affname = yang_dnode_get_string(args->dnode, ".");
affinity_mode = yang_dnode_get_enum(args->dnode, "../../affinity-mode");
if (!ifp)
return NB_ERR_RESOURCE;
affmap = affinity_map_get(affname);
iflp = if_link_params_get(ifp);
switch (args->event) {
case NB_EV_VALIDATE:
if (!affmap) {
snprintf(args->errmsg, args->errmsg_len,
"affinity-map %s not found.", affname);
return NB_ERR_VALIDATION;
}
if (affinity_mode == AFFINITY_MODE_STANDARD &&
affmap->bit_position > 31) {
snprintf(
args->errmsg, args->errmsg_len,
"affinity %s bit-position %d is not compatible with affinity-mode standard (bit-position > 31).",
affname, affmap->bit_position);
return NB_ERR_VALIDATION;
}
break;
case NB_EV_PREPARE:
case NB_EV_ABORT:
break;
case NB_EV_APPLY:
if (!iflp)
iflp = if_link_params_enable(ifp);
if (affmap->bit_position < 32 &&
(affinity_mode == AFFINITY_MODE_STANDARD ||
affinity_mode == AFFINITY_MODE_BOTH)) {
iflp->admin_grp |= 1 << affmap->bit_position;
SET_PARAM(iflp, LP_ADM_GRP);
}
if (affinity_mode == AFFINITY_MODE_EXTENDED ||
affinity_mode == AFFINITY_MODE_BOTH) {
admin_group_set(&iflp->ext_admin_grp,
affmap->bit_position);
SET_PARAM(iflp, LP_EXTEND_ADM_GRP);
}
if (if_is_operative(ifp))
zebra_interface_parameters_update(ifp);
break;
}
return NB_OK;
}
int lib_interface_zebra_affinity_destroy(struct nb_cb_destroy_args *args)
{
struct interface *ifp;
const char *affname;
struct if_link_params *iflp;
struct affinity_map *affmap;
enum affinity_mode affinity_mode;
ifp = nb_running_get_entry(args->dnode, NULL, true);
affname = yang_dnode_get_string(args->dnode, ".");
affinity_mode = yang_dnode_get_enum(args->dnode, "../../affinity-mode");
if (!ifp)
return NB_ERR_RESOURCE;
affmap = affinity_map_get(affname);
iflp = if_link_params_get(ifp);
switch (args->event) {
case NB_EV_VALIDATE:
if (!affmap) {
snprintf(args->errmsg, args->errmsg_len,
"affinity-map %s not found.", affname);
return NB_ERR_VALIDATION;
}
break;
case NB_EV_PREPARE:
case NB_EV_ABORT:
break;
case NB_EV_APPLY:
if (!iflp)
return NB_OK;
if (affmap->bit_position < 32 &&
(affinity_mode == AFFINITY_MODE_STANDARD ||
affinity_mode == AFFINITY_MODE_BOTH)) {
iflp->admin_grp &= ~(1 << affmap->bit_position);
if (iflp->admin_grp == 0)
UNSET_PARAM(iflp, LP_ADM_GRP);
}
if (affinity_mode == AFFINITY_MODE_EXTENDED ||
affinity_mode == AFFINITY_MODE_BOTH) {
admin_group_unset(&iflp->ext_admin_grp,
affmap->bit_position);
if (admin_group_zero(&iflp->ext_admin_grp))
UNSET_PARAM(iflp, LP_EXTEND_ADM_GRP);
}
if (if_is_operative(ifp))
zebra_interface_parameters_update(ifp);
break;
}
return NB_OK;
}
/*
* XPath:
* /frr-interface:lib/interface/frr-zebra:zebra/link-params/affinity-mode
*/
int lib_interface_zebra_affinity_mode_modify(struct nb_cb_modify_args *args)
{
struct interface *ifp;
struct if_link_params *iflp;
enum affinity_mode affinity_mode;
ifp = nb_running_get_entry(args->dnode, NULL, true);
affinity_mode = yang_dnode_get_enum(args->dnode, ".");
if (!ifp)
return NB_ERR_RESOURCE;
iflp = if_link_params_get(ifp);
switch (args->event) {
case NB_EV_VALIDATE:
if (affinity_mode == AFFINITY_MODE_STANDARD &&
admin_group_nb_words(&iflp->ext_admin_grp) > 1) {
snprintf(
args->errmsg, args->errmsg_len,
"affinity-mode standard cannot be set when a bit-position > 31 is set.");
return NB_ERR_VALIDATION;
}
break;
case NB_EV_PREPARE:
case NB_EV_ABORT:
break;
case NB_EV_APPLY:
if (!iflp)
iflp = if_link_params_enable(ifp);
if (affinity_mode == AFFINITY_MODE_STANDARD) {
if (!IS_PARAM_SET(iflp, LP_ADM_GRP) &&
IS_PARAM_SET(iflp, LP_EXTEND_ADM_GRP)) {
iflp->admin_grp = admin_group_get_offset(
&iflp->ext_admin_grp, 0);
SET_PARAM(iflp, LP_ADM_GRP);
}
admin_group_clear(&iflp->ext_admin_grp);
UNSET_PARAM(iflp, LP_EXTEND_ADM_GRP);
}
if (affinity_mode == AFFINITY_MODE_EXTENDED) {
if (!IS_PARAM_SET(iflp, LP_EXTEND_ADM_GRP) &&
IS_PARAM_SET(iflp, LP_ADM_GRP)) {
admin_group_bulk_set(&iflp->ext_admin_grp,
iflp->admin_grp, 0);
SET_PARAM(iflp, LP_EXTEND_ADM_GRP);
}
iflp->admin_grp = 0;
UNSET_PARAM(iflp, LP_ADM_GRP);
}
if (affinity_mode == AFFINITY_MODE_BOTH) {
if (!IS_PARAM_SET(iflp, LP_EXTEND_ADM_GRP) &&
IS_PARAM_SET(iflp, LP_ADM_GRP)) {
admin_group_bulk_set(&iflp->ext_admin_grp,
iflp->admin_grp, 0);
SET_PARAM(iflp, LP_EXTEND_ADM_GRP);
} else if (!IS_PARAM_SET(iflp, LP_ADM_GRP) &&
IS_PARAM_SET(iflp, LP_EXTEND_ADM_GRP)) {
iflp->admin_grp = admin_group_get_offset(
&iflp->ext_admin_grp, 0);
SET_PARAM(iflp, LP_ADM_GRP);
}
}
if (if_is_operative(ifp))
zebra_interface_parameters_update(ifp);
break;
}
return NB_OK;
}
/*
* XPath: /frr-vrf:lib/vrf/frr-zebra:zebra/l3vni-id
*/

View File

@ -34,6 +34,7 @@
#include "srcdest_table.h"
#include "vxlan.h"
#include "termtable.h"
#include "affinitymap.h"
#include "zebra/zebra_router.h"
#include "zebra/zserv.h"
@ -41,6 +42,7 @@
#include "zebra/zebra_mpls.h"
#include "zebra/zebra_rnh.h"
#include "zebra/redistribute.h"
#include "zebra/zebra_affinitymap.h"
#include "zebra/zebra_routemap.h"
#include "lib/json.h"
#include "lib/route_opaque.h"
@ -4554,6 +4556,8 @@ void zebra_vty_init(void)
/* Route-map */
zebra_route_map_init();
zebra_affinity_map_init();
install_node(&ip_node);
install_node(&protocol_node);