From 2f8cc0e565b064b5cac8503a9a927583235845e3 Mon Sep 17 00:00:00 2001 From: Donatas Abraitis Date: Mon, 7 Oct 2019 21:56:51 +0300 Subject: [PATCH 1/2] bgpd: Use sequence numbers for community lists This patch allows using sequence numbers for community lists. We already have this for prefix-lists and access-lists. Signed-off-by: Donatas Abraitis --- bgpd/bgp_clist.c | 136 +++++++++++++++++++++++++++------ bgpd/bgp_clist.h | 27 ++++--- bgpd/bgp_vty.c | 190 ++++++++++++++++++++++++++++++++++++----------- 3 files changed, 276 insertions(+), 77 deletions(-) diff --git a/bgpd/bgp_clist.c b/bgpd/bgp_clist.c index 29e668d179..7ca48a5bea 100644 --- a/bgpd/bgp_clist.c +++ b/bgpd/bgp_clist.c @@ -37,6 +37,37 @@ #include "bgpd/bgp_regex.h" #include "bgpd/bgp_clist.h" +/* Calculate new sequential number. */ +static int64_t bgp_clist_new_seq_get(struct community_list *list) +{ + int64_t maxseq; + int64_t newseq; + struct community_entry *entry; + + maxseq = newseq = 0; + + for (entry = list->head; entry; entry = entry->next) { + if (maxseq < entry->seq) + maxseq = entry->seq; + } + + newseq = ((maxseq / 5) * 5) + 5; + + return (newseq > UINT_MAX) ? UINT_MAX : newseq; +} + +/* Return community-list entry which has same seq number. */ +static struct community_entry *bgp_clist_seq_check(struct community_list *list, + int64_t seq) +{ + struct community_entry *entry; + + for (entry = list->head; entry; entry = entry->next) + if (entry->seq == seq) + return entry; + return NULL; +} + static uint32_t bgp_clist_hash_key_community_list(const void *data) { struct community_list *cl = (struct community_list *) data; @@ -285,20 +316,6 @@ static int community_list_empty_p(struct community_list *list) return (list->head == NULL && list->tail == NULL) ? 1 : 0; } -/* Add community-list entry to the list. */ -static void community_list_entry_add(struct community_list *list, - struct community_entry *entry) -{ - entry->next = NULL; - entry->prev = list->tail; - - if (list->tail) - list->tail->next = entry; - else - list->head = entry; - list->tail = entry; -} - /* Delete community-list entry from the list. */ static void community_list_entry_delete(struct community_list_master *cm, struct community_list *list, @@ -320,6 +337,57 @@ static void community_list_entry_delete(struct community_list_master *cm, community_list_delete(cm, list); } +/* Add community-list entry to the list. */ +static void community_list_entry_add(struct community_list *list, + struct community_entry *entry, + struct community_list_handler *ch, + int master) +{ + struct community_list_master *cm = NULL; + struct community_entry *replace; + struct community_entry *point; + + cm = community_list_master_lookup(ch, master); + + /* Automatic assignment of seq no. */ + if (entry->seq == COMMUNITY_SEQ_NUMBER_AUTO) + entry->seq = bgp_clist_new_seq_get(list); + + if (list->tail && entry->seq > list->tail->seq) + point = NULL; + else { + replace = bgp_clist_seq_check(list, entry->seq); + if (replace) + community_list_entry_delete(cm, list, entry); + + /* Check insert point. */ + for (point = list->head; point; point = point->next) + if (point->seq >= entry->seq) + break; + } + + /* In case of this is the first element of the list. */ + entry->next = point; + + if (point) { + if (point->prev) + point->prev->next = entry; + else + list->head = entry; + + entry->prev = point->prev; + point->prev = entry; + } else { + if (list->tail) + list->tail->next = entry; + else + list->head = entry; + + entry->prev = list->tail; + list->tail = entry; + } +} + /* Lookup community-list entry from the list. */ static struct community_entry * community_list_entry_lookup(struct community_list *list, const void *arg, @@ -878,12 +946,16 @@ static int community_list_dup_check(struct community_list *list, /* Set community-list. */ int community_list_set(struct community_list_handler *ch, const char *name, - const char *str, int direct, int style) + const char *str, const char *seq, int direct, int style) { struct community_entry *entry = NULL; struct community_list *list; struct community *com = NULL; regex_t *regex = NULL; + int64_t seqnum = COMMUNITY_SEQ_NUMBER_AUTO; + + if (seq) + seqnum = (int64_t)atol(seq); /* Get community list. */ list = community_list_get(ch, name, COMMUNITY_LIST_MASTER); @@ -919,6 +991,7 @@ int community_list_set(struct community_list_handler *ch, const char *name, entry->any = (str ? 0 : 1); entry->u.com = com; entry->reg = regex; + entry->seq = seqnum; entry->config = (regex ? XSTRDUP(MTYPE_COMMUNITY_LIST_CONFIG, str) : NULL); @@ -926,7 +999,8 @@ int community_list_set(struct community_list_handler *ch, const char *name, if (community_list_dup_check(list, entry)) community_entry_free(entry); else { - community_list_entry_add(list, entry); + community_list_entry_add(list, entry, ch, + COMMUNITY_LIST_MASTER); route_map_notify_dependencies(name, RMAP_EVENT_CLIST_ADDED); } @@ -935,7 +1009,8 @@ int community_list_set(struct community_list_handler *ch, const char *name, /* Unset community-list */ int community_list_unset(struct community_list_handler *ch, const char *name, - const char *str, int direct, int style) + const char *str, const char *seq, int direct, + int style) { struct community_list_master *cm = NULL; struct community_entry *entry = NULL; @@ -1057,12 +1132,16 @@ static int lcommunity_list_valid(const char *community) /* Set lcommunity-list. */ int lcommunity_list_set(struct community_list_handler *ch, const char *name, - const char *str, int direct, int style) + const char *str, const char *seq, int direct, int style) { struct community_entry *entry = NULL; struct community_list *list; struct lcommunity *lcom = NULL; regex_t *regex = NULL; + int64_t seqnum = COMMUNITY_SEQ_NUMBER_AUTO; + + if (seq) + seqnum = (int64_t)atol(seq); /* Get community list. */ list = community_list_get(ch, name, LARGE_COMMUNITY_LIST_MASTER); @@ -1101,6 +1180,7 @@ int lcommunity_list_set(struct community_list_handler *ch, const char *name, entry->any = (str ? 0 : 1); entry->u.lcom = lcom; entry->reg = regex; + entry->seq = seqnum; entry->config = (regex ? XSTRDUP(MTYPE_COMMUNITY_LIST_CONFIG, str) : NULL); @@ -1108,7 +1188,8 @@ int lcommunity_list_set(struct community_list_handler *ch, const char *name, if (community_list_dup_check(list, entry)) community_entry_free(entry); else { - community_list_entry_add(list, entry); + community_list_entry_add(list, entry, ch, + LARGE_COMMUNITY_LIST_MASTER); route_map_notify_dependencies(name, RMAP_EVENT_LLIST_ADDED); } @@ -1118,7 +1199,8 @@ int lcommunity_list_set(struct community_list_handler *ch, const char *name, /* Unset community-list. When str is NULL, delete all of community-list entry belongs to the specified name. */ int lcommunity_list_unset(struct community_list_handler *ch, const char *name, - const char *str, int direct, int style) + const char *str, const char *seq, int direct, + int style) { struct community_list_master *cm = NULL; struct community_entry *entry = NULL; @@ -1168,12 +1250,17 @@ int lcommunity_list_unset(struct community_list_handler *ch, const char *name, /* Set extcommunity-list. */ int extcommunity_list_set(struct community_list_handler *ch, const char *name, - const char *str, int direct, int style) + const char *str, const char *seq, int direct, + int style) { struct community_entry *entry = NULL; struct community_list *list; struct ecommunity *ecom = NULL; regex_t *regex = NULL; + int64_t seqnum = COMMUNITY_SEQ_NUMBER_AUTO; + + if (seq) + seqnum = (int64_t)atol(seq); if (str == NULL) return COMMUNITY_LIST_ERR_MALFORMED_VAL; @@ -1220,12 +1307,14 @@ int extcommunity_list_set(struct community_list_handler *ch, const char *name, entry->u.ecom = ecom; entry->reg = regex; + entry->seq = seqnum; /* Do not put duplicated community entry. */ if (community_list_dup_check(list, entry)) community_entry_free(entry); else { - community_list_entry_add(list, entry); + community_list_entry_add(list, entry, ch, + EXTCOMMUNITY_LIST_MASTER); route_map_notify_dependencies(name, RMAP_EVENT_ECLIST_ADDED); } @@ -1238,7 +1327,8 @@ int extcommunity_list_set(struct community_list_handler *ch, const char *name, * specified name. */ int extcommunity_list_unset(struct community_list_handler *ch, const char *name, - const char *str, int direct, int style) + const char *str, const char *seq, int direct, + int style) { struct community_list_master *cm = NULL; struct community_entry *entry = NULL; diff --git a/bgpd/bgp_clist.h b/bgpd/bgp_clist.h index 87b29ac3be..c5718aecac 100644 --- a/bgpd/bgp_clist.h +++ b/bgpd/bgp_clist.h @@ -36,6 +36,8 @@ #define COMMUNITY_LIST_STRING 0 #define COMMUNITY_LIST_NUMBER 1 +#define COMMUNITY_SEQ_NUMBER_AUTO -1 + /* Community-list entry types. */ #define COMMUNITY_LIST_STANDARD 0 /* Standard community-list. */ #define COMMUNITY_LIST_EXPANDED 1 /* Expanded community-list. */ @@ -81,6 +83,9 @@ struct community_entry { /* Any match. */ uint8_t any; + /* Sequence number. */ + int64_t seq; + /* Community structure. */ union { struct community *com; @@ -135,23 +140,23 @@ extern struct community_list_handler *community_list_init(void); extern void community_list_terminate(struct community_list_handler *); extern int community_list_set(struct community_list_handler *ch, - const char *name, const char *str, int direct, - int style); + const char *name, const char *str, + const char *seq, int direct, int style); extern int community_list_unset(struct community_list_handler *ch, - const char *name, const char *str, int direct, - int style); + const char *name, const char *str, + const char *seq, int direct, int style); extern int extcommunity_list_set(struct community_list_handler *ch, - const char *name, const char *str, int direct, - int style); + const char *name, const char *str, + const char *seq, int direct, int style); extern int extcommunity_list_unset(struct community_list_handler *ch, const char *name, const char *str, - int direct, int style); + const char *seq, int direct, int style); extern int lcommunity_list_set(struct community_list_handler *ch, - const char *name, const char *str, int direct, - int style); + const char *name, const char *str, + const char *seq, int direct, int style); extern int lcommunity_list_unset(struct community_list_handler *ch, - const char *name, const char *str, int direct, - int style); + const char *name, const char *str, + const char *seq, int direct, int style); extern struct community_list_master * community_list_master_lookup(struct community_list_handler *, int); diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index eae9db5a61..34afb16149 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -14240,21 +14240,29 @@ static void community_list_perror(struct vty *vty, int ret) /*community-list standard */ DEFUN (community_list_standard, bgp_community_list_standard_cmd, - "bgp community-list <(1-99)|standard WORD> AA:NN...", + "bgp community-list <(1-99)|standard WORD> [seq (1-4294967295)] AA:NN...", BGP_STR COMMUNITY_LIST_STR "Community list number (standard)\n" "Add an standard community-list entry\n" "Community list name\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify community to reject\n" "Specify community to accept\n" COMMUNITY_VAL_STR) { char *cl_name_or_number = NULL; + char *seq = NULL; int direct = 0; int style = COMMUNITY_LIST_STANDARD; int idx = 0; + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; argv_find(argv, argc, "(1-99)", &idx); argv_find(argv, argc, "WORD", &idx); cl_name_or_number = argv[idx]->arg; @@ -14263,8 +14271,8 @@ DEFUN (community_list_standard, argv_find(argv, argc, "AA:NN", &idx); char *str = argv_concat(argv, argc, idx); - int ret = community_list_set(bgp_clist, cl_name_or_number, str, direct, - style); + int ret = community_list_set(bgp_clist, cl_name_or_number, str, seq, + direct, style); XFREE(MTYPE_TMP, str); @@ -14279,13 +14287,15 @@ DEFUN (community_list_standard, DEFUN (no_community_list_standard_all, no_bgp_community_list_standard_all_cmd, - "no bgp community-list <(1-99)|standard WORD> AA:NN...", + "no bgp community-list <(1-99)|standard WORD> [seq (1-4294967295)] AA:NN...", NO_STR BGP_STR COMMUNITY_LIST_STR "Community list number (standard)\n" "Add an standard community-list entry\n" "Community list name\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify community to reject\n" "Specify community to accept\n" COMMUNITY_VAL_STR) @@ -14294,9 +14304,14 @@ DEFUN (no_community_list_standard_all, char *str = NULL; int direct = 0; int style = COMMUNITY_LIST_STANDARD; - + char *seq = NULL; int idx = 0; + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; argv_find(argv, argc, "permit", &idx); argv_find(argv, argc, "deny", &idx); @@ -14315,7 +14330,7 @@ DEFUN (no_community_list_standard_all, argv_find(argv, argc, "WORD", &idx); cl_name_or_number = argv[idx]->arg; - int ret = community_list_unset(bgp_clist, cl_name_or_number, str, + int ret = community_list_unset(bgp_clist, cl_name_or_number, str, seq, direct, style); XFREE(MTYPE_TMP, str); @@ -14338,22 +14353,30 @@ ALIAS(no_community_list_standard_all, no_bgp_community_list_standard_all_list_cm /*community-list expanded */ DEFUN (community_list_expanded_all, bgp_community_list_expanded_all_cmd, - "bgp community-list <(100-500)|expanded WORD> AA:NN...", + "bgp community-list <(100-500)|expanded WORD> [seq (1-4294967295)] AA:NN...", BGP_STR COMMUNITY_LIST_STR "Community list number (expanded)\n" "Add an expanded community-list entry\n" "Community list name\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify community to reject\n" "Specify community to accept\n" COMMUNITY_VAL_STR) { char *cl_name_or_number = NULL; + char *seq = NULL; int direct = 0; int style = COMMUNITY_LIST_EXPANDED; - int idx = 0; + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "(100-500)", &idx); argv_find(argv, argc, "WORD", &idx); cl_name_or_number = argv[idx]->arg; @@ -14362,8 +14385,8 @@ DEFUN (community_list_expanded_all, argv_find(argv, argc, "AA:NN", &idx); char *str = argv_concat(argv, argc, idx); - int ret = community_list_set(bgp_clist, cl_name_or_number, str, direct, - style); + int ret = community_list_set(bgp_clist, cl_name_or_number, str, seq, + direct, style); XFREE(MTYPE_TMP, str); @@ -14378,24 +14401,31 @@ DEFUN (community_list_expanded_all, DEFUN (no_community_list_expanded_all, no_bgp_community_list_expanded_all_cmd, - "no bgp community-list <(100-500)|expanded WORD> AA:NN...", + "no bgp community-list <(100-500)|expanded WORD> [seq (1-4294967295)] AA:NN...", NO_STR BGP_STR COMMUNITY_LIST_STR "Community list number (expanded)\n" "Add an expanded community-list entry\n" "Community list name\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify community to reject\n" "Specify community to accept\n" COMMUNITY_VAL_STR) { char *cl_name_or_number = NULL; + char *seq = NULL; char *str = NULL; int direct = 0; int style = COMMUNITY_LIST_EXPANDED; - int idx = 0; + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; argv_find(argv, argc, "permit", &idx); argv_find(argv, argc, "deny", &idx); @@ -14414,7 +14444,7 @@ DEFUN (no_community_list_expanded_all, argv_find(argv, argc, "WORD", &idx); cl_name_or_number = argv[idx]->arg; - int ret = community_list_unset(bgp_clist, cl_name_or_number, str, + int ret = community_list_unset(bgp_clist, cl_name_or_number, str, seq, direct, style); XFREE(MTYPE_TMP, str); @@ -14541,7 +14571,13 @@ static int lcommunity_list_set_vty(struct vty *vty, int argc, char *str; int idx = 0; char *cl_name; + char *seq = NULL; + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; direct = argv_find(argv, argc, "permit", &idx) ? COMMUNITY_PERMIT : COMMUNITY_DENY; @@ -14565,7 +14601,7 @@ static int lcommunity_list_set_vty(struct vty *vty, int argc, else str = NULL; - ret = lcommunity_list_set(bgp_clist, cl_name, str, direct, style); + ret = lcommunity_list_set(bgp_clist, cl_name, str, seq, direct, style); /* Free temporary community list string allocated by argv_concat(). */ @@ -14585,7 +14621,13 @@ static int lcommunity_list_unset_vty(struct vty *vty, int argc, int direct = 0; char *str = NULL; int idx = 0; + char *seq = NULL; + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; argv_find(argv, argc, "permit", &idx); argv_find(argv, argc, "deny", &idx); @@ -14609,7 +14651,7 @@ static int lcommunity_list_unset_vty(struct vty *vty, int argc, argv_find(argv, argc, "WORD", &idx); /* Unset community list. */ - ret = lcommunity_list_unset(bgp_clist, argv[idx]->arg, str, direct, + ret = lcommunity_list_unset(bgp_clist, argv[idx]->arg, str, seq, direct, style); /* Free temporary community list string allocated by @@ -14630,10 +14672,12 @@ static int lcommunity_list_unset_vty(struct vty *vty, int argc, DEFUN (lcommunity_list_standard, bgp_lcommunity_list_standard_cmd, - "bgp large-community-list (1-99) AA:BB:CC...", + "bgp large-community-list (1-99) [seq (1-4294967295)] AA:BB:CC...", BGP_STR LCOMMUNITY_LIST_STR "Large Community list number (standard)\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify large community to reject\n" "Specify large community to accept\n" LCOMMUNITY_VAL_STR) @@ -14644,10 +14688,12 @@ DEFUN (lcommunity_list_standard, DEFUN (lcommunity_list_expanded, bgp_lcommunity_list_expanded_cmd, - "bgp large-community-list (100-500) LINE...", + "bgp large-community-list (100-500) [seq (1-4294967295)] LINE...", BGP_STR LCOMMUNITY_LIST_STR "Large Community list number (expanded)\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify large community to reject\n" "Specify large community to accept\n" "An ordered list as a regular-expression\n") @@ -14658,11 +14704,13 @@ DEFUN (lcommunity_list_expanded, DEFUN (lcommunity_list_name_standard, bgp_lcommunity_list_name_standard_cmd, - "bgp large-community-list standard WORD AA:BB:CC...", + "bgp large-community-list standard WORD [seq (1-4294967295)] AA:BB:CC...", BGP_STR LCOMMUNITY_LIST_STR "Specify standard large-community-list\n" "Large Community list name\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify large community to reject\n" "Specify large community to accept\n" LCOMMUNITY_VAL_STR) @@ -14673,11 +14721,13 @@ DEFUN (lcommunity_list_name_standard, DEFUN (lcommunity_list_name_expanded, bgp_lcommunity_list_name_expanded_cmd, - "bgp large-community-list expanded WORD LINE...", + "bgp large-community-list expanded WORD [seq (1-4294967295)] LINE...", BGP_STR LCOMMUNITY_LIST_STR "Specify expanded large-community-list\n" "Large Community list name\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify large community to reject\n" "Specify large community to accept\n" "An ordered list as a regular-expression\n") @@ -14715,11 +14765,13 @@ DEFUN (no_lcommunity_list_name_expanded_all, DEFUN (no_lcommunity_list_standard, no_bgp_lcommunity_list_standard_cmd, - "no bgp large-community-list (1-99) AA:AA:NN...", + "no bgp large-community-list (1-99) [seq (1-4294967295)] AA:AA:NN...", NO_STR BGP_STR LCOMMUNITY_LIST_STR "Large Community list number (standard)\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify large community to reject\n" "Specify large community to accept\n" LCOMMUNITY_VAL_STR) @@ -14730,11 +14782,13 @@ DEFUN (no_lcommunity_list_standard, DEFUN (no_lcommunity_list_expanded, no_bgp_lcommunity_list_expanded_cmd, - "no bgp large-community-list (100-500) LINE...", + "no bgp large-community-list (100-500) [seq (1-4294967295)] LINE...", NO_STR BGP_STR LCOMMUNITY_LIST_STR "Large Community list number (expanded)\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify large community to reject\n" "Specify large community to accept\n" "An ordered list as a regular-expression\n") @@ -14745,12 +14799,14 @@ DEFUN (no_lcommunity_list_expanded, DEFUN (no_lcommunity_list_name_standard, no_bgp_lcommunity_list_name_standard_cmd, - "no bgp large-community-list standard WORD AA:AA:NN...", + "no bgp large-community-list standard WORD [seq (1-4294967295)] AA:AA:NN...", NO_STR BGP_STR LCOMMUNITY_LIST_STR "Specify standard large-community-list\n" "Large Community list name\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify large community to reject\n" "Specify large community to accept\n" LCOMMUNITY_VAL_STR) @@ -14761,12 +14817,14 @@ DEFUN (no_lcommunity_list_name_standard, DEFUN (no_lcommunity_list_name_expanded, no_bgp_lcommunity_list_name_expanded_cmd, - "no bgp large-community-list expanded WORD LINE...", + "no bgp large-community-list expanded WORD [seq (1-4294967295)] LINE...", NO_STR BGP_STR LCOMMUNITY_LIST_STR "Specify expanded large-community-list\n" "Large community list name\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify large community to reject\n" "Specify large community to accept\n" "An ordered list as a regular-expression\n") @@ -14861,12 +14919,14 @@ DEFUN (show_lcommunity_list_arg, DEFUN (extcommunity_list_standard, bgp_extcommunity_list_standard_cmd, - "bgp extcommunity-list <(1-99)|standard WORD> AA:NN...", + "bgp extcommunity-list <(1-99)|standard WORD> [seq (1-4294967295)] AA:NN...", BGP_STR EXTCOMMUNITY_LIST_STR "Extended Community list number (standard)\n" "Specify standard extcommunity-list\n" "Community list name\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify community to reject\n" "Specify community to accept\n" EXTCOMMUNITY_VAL_STR) @@ -14874,18 +14934,24 @@ DEFUN (extcommunity_list_standard, int style = EXTCOMMUNITY_LIST_STANDARD; int direct = 0; char *cl_number_or_name = NULL; + char *seq = NULL; int idx = 0; argv_find(argv, argc, "(1-99)", &idx); argv_find(argv, argc, "WORD", &idx); cl_number_or_name = argv[idx]->arg; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + direct = argv_find(argv, argc, "permit", &idx) ? COMMUNITY_PERMIT : COMMUNITY_DENY; argv_find(argv, argc, "AA:NN", &idx); char *str = argv_concat(argv, argc, idx); - int ret = extcommunity_list_set(bgp_clist, cl_number_or_name, str, + int ret = extcommunity_list_set(bgp_clist, cl_number_or_name, str, seq, direct, style); XFREE(MTYPE_TMP, str); @@ -14900,12 +14966,14 @@ DEFUN (extcommunity_list_standard, DEFUN (extcommunity_list_name_expanded, bgp_extcommunity_list_name_expanded_cmd, - "bgp extcommunity-list <(100-500)|expanded WORD> LINE...", + "bgp extcommunity-list <(100-500)|expanded WORD> [seq (1-4294967295)] LINE...", BGP_STR EXTCOMMUNITY_LIST_STR "Extended Community list number (expanded)\n" "Specify expanded extcommunity-list\n" "Extended Community list name\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify community to reject\n" "Specify community to accept\n" "An ordered list as a regular-expression\n") @@ -14913,17 +14981,23 @@ DEFUN (extcommunity_list_name_expanded, int style = EXTCOMMUNITY_LIST_EXPANDED; int direct = 0; char *cl_number_or_name = NULL; + char *seq = NULL; int idx = 0; argv_find(argv, argc, "(100-500)", &idx); argv_find(argv, argc, "WORD", &idx); cl_number_or_name = argv[idx]->arg; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + direct = argv_find(argv, argc, "permit", &idx) ? COMMUNITY_PERMIT : COMMUNITY_DENY; argv_find(argv, argc, "LINE", &idx); char *str = argv_concat(argv, argc, idx); - int ret = extcommunity_list_set(bgp_clist, cl_number_or_name, str, + int ret = extcommunity_list_set(bgp_clist, cl_number_or_name, str, seq, direct, style); XFREE(MTYPE_TMP, str); @@ -14938,13 +15012,15 @@ DEFUN (extcommunity_list_name_expanded, DEFUN (no_extcommunity_list_standard_all, no_bgp_extcommunity_list_standard_all_cmd, - "no bgp extcommunity-list <(1-99)|standard WORD> AA:NN...", + "no bgp extcommunity-list <(1-99)|standard WORD> [seq (1-4294967295)] AA:NN...", NO_STR BGP_STR EXTCOMMUNITY_LIST_STR "Extended Community list number (standard)\n" "Specify standard extcommunity-list\n" "Community list name\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify community to reject\n" "Specify community to accept\n" EXTCOMMUNITY_VAL_STR) @@ -14953,11 +15029,16 @@ DEFUN (no_extcommunity_list_standard_all, int direct = 0; char *cl_number_or_name = NULL; char *str = NULL; + char *seq = NULL; int idx = 0; + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; argv_find(argv, argc, "permit", &idx); argv_find(argv, argc, "deny", &idx); - if (idx) { direct = argv_find(argv, argc, "permit", &idx) ? COMMUNITY_PERMIT @@ -14974,7 +15055,7 @@ DEFUN (no_extcommunity_list_standard_all, cl_number_or_name = argv[idx]->arg; int ret = extcommunity_list_unset(bgp_clist, cl_number_or_name, str, - direct, style); + seq, direct, style); XFREE(MTYPE_TMP, str); @@ -14996,13 +15077,15 @@ ALIAS(no_extcommunity_list_standard_all, DEFUN (no_extcommunity_list_expanded_all, no_bgp_extcommunity_list_expanded_all_cmd, - "no bgp extcommunity-list <(100-500)|expanded WORD> LINE...", + "no bgp extcommunity-list <(100-500)|expanded WORD> [seq (1-4294967295)] LINE...", NO_STR BGP_STR EXTCOMMUNITY_LIST_STR "Extended Community list number (expanded)\n" "Specify expanded extcommunity-list\n" "Extended Community list name\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify community to reject\n" "Specify community to accept\n" "An ordered list as a regular-expression\n") @@ -15011,8 +15094,14 @@ DEFUN (no_extcommunity_list_expanded_all, int direct = 0; char *cl_number_or_name = NULL; char *str = NULL; + char *seq = NULL; int idx = 0; + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; argv_find(argv, argc, "permit", &idx); argv_find(argv, argc, "deny", &idx); @@ -15032,7 +15121,7 @@ DEFUN (no_extcommunity_list_expanded_all, cl_number_or_name = argv[idx]->arg; int ret = extcommunity_list_unset(bgp_clist, cl_number_or_name, str, - direct, style); + seq, direct, style); XFREE(MTYPE_TMP, str); @@ -15143,18 +15232,22 @@ static int community_list_config_write(struct vty *vty) for (list = cm->num.head; list; list = list->next) for (entry = list->head; entry; entry = entry->next) { - vty_out(vty, "bgp community-list %s %s %s\n", list->name, + vty_out(vty, + "bgp community-list %s seq %" PRId64 " %s %s\n", + list->name, entry->seq, community_direct_str(entry->direct), community_list_config_str(entry)); write++; } for (list = cm->str.head; list; list = list->next) for (entry = list->head; entry; entry = entry->next) { - vty_out(vty, "bgp community-list %s %s %s %s\n", + vty_out(vty, + "bgp community-list %s %s seq %" PRId64 " %s %s\n", entry->style == COMMUNITY_LIST_STANDARD ? "standard" : "expanded", - list->name, community_direct_str(entry->direct), + list->name, entry->seq, + community_direct_str(entry->direct), community_list_config_str(entry)); write++; } @@ -15164,18 +15257,23 @@ static int community_list_config_write(struct vty *vty) for (list = cm->num.head; list; list = list->next) for (entry = list->head; entry; entry = entry->next) { - vty_out(vty, "bgp extcommunity-list %s %s %s\n", - list->name, community_direct_str(entry->direct), + vty_out(vty, + "bgp extcommunity-list %s seq %" PRId64 " %s %s\n", + list->name, entry->seq, + community_direct_str(entry->direct), community_list_config_str(entry)); write++; } for (list = cm->str.head; list; list = list->next) for (entry = list->head; entry; entry = entry->next) { - vty_out(vty, "bgp extcommunity-list %s %s %s %s\n", + vty_out(vty, + "bgp extcommunity-list %s %s seq %" PRId64 + " %s %s\n", entry->style == EXTCOMMUNITY_LIST_STANDARD ? "standard" : "expanded", - list->name, community_direct_str(entry->direct), + list->name, entry->seq, + community_direct_str(entry->direct), community_list_config_str(entry)); write++; } @@ -15187,18 +15285,24 @@ static int community_list_config_write(struct vty *vty) for (list = cm->num.head; list; list = list->next) for (entry = list->head; entry; entry = entry->next) { - vty_out(vty, "bgp large-community-list %s %s %s\n", - list->name, community_direct_str(entry->direct), + vty_out(vty, + "bgp large-community-list %s seq %" PRId64 + " %s %s\n", + list->name, entry->seq, + community_direct_str(entry->direct), community_list_config_str(entry)); write++; } for (list = cm->str.head; list; list = list->next) for (entry = list->head; entry; entry = entry->next) { - vty_out(vty, "bgp large-community-list %s %s %s %s\n", + vty_out(vty, + "bgp large-community-list %s %s seq %" PRId64 + " %s %s\n", + entry->style == LARGE_COMMUNITY_LIST_STANDARD ? "standard" : "expanded", - list->name, community_direct_str(entry->direct), + list->name, entry->seq, community_direct_str(entry->direct), community_list_config_str(entry)); write++; } From 4378f57c3ed0c06c891cc43e726e7332034e1454 Mon Sep 17 00:00:00 2001 From: Donatas Abraitis Date: Thu, 24 Oct 2019 15:40:23 +0300 Subject: [PATCH 2/2] bgpd: Allow deleting by `no bgp large-community-list standard WORD` Without with fix we can't delete large-community-list using no bgp large-community-list standard WORD, but no bgp large-community-list WORD Let's keep this identical what we have with expanded lists as well. Signed-off-by: Donatas Abraitis --- bgpd/bgp_vty.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 34afb16149..5c382be45d 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -14736,8 +14736,8 @@ DEFUN (lcommunity_list_name_expanded, LARGE_COMMUNITY_LIST_EXPANDED, 1); } -DEFUN (no_lcommunity_list_standard_all, - no_bgp_lcommunity_list_standard_all_cmd, +DEFUN (no_lcommunity_list_all, + no_bgp_lcommunity_list_all_cmd, "no bgp large-community-list <(1-99)|(100-500)|WORD>", NO_STR BGP_STR @@ -14750,6 +14750,19 @@ DEFUN (no_lcommunity_list_standard_all, LARGE_COMMUNITY_LIST_STANDARD); } +DEFUN (no_lcommunity_list_name_standard_all, + no_bgp_lcommunity_list_name_standard_all_cmd, + "no bgp large-community-list standard WORD", + NO_STR + BGP_STR + LCOMMUNITY_LIST_STR + "Specify standard large-community-list\n" + "Large Community list name\n") +{ + return lcommunity_list_unset_vty(vty, argc, argv, + LARGE_COMMUNITY_LIST_STANDARD); +} + DEFUN (no_lcommunity_list_name_expanded_all, no_bgp_lcommunity_list_name_expanded_all_cmd, "no bgp large-community-list expanded WORD", @@ -15345,7 +15358,9 @@ static void community_list_vty(void) install_element(CONFIG_NODE, &bgp_lcommunity_list_expanded_cmd); install_element(CONFIG_NODE, &bgp_lcommunity_list_name_standard_cmd); install_element(CONFIG_NODE, &bgp_lcommunity_list_name_expanded_cmd); - install_element(CONFIG_NODE, &no_bgp_lcommunity_list_standard_all_cmd); + install_element(CONFIG_NODE, &no_bgp_lcommunity_list_all_cmd); + install_element(CONFIG_NODE, + &no_bgp_lcommunity_list_name_standard_all_cmd); install_element(CONFIG_NODE, &no_bgp_lcommunity_list_name_expanded_all_cmd); install_element(CONFIG_NODE, &no_bgp_lcommunity_list_standard_cmd);