diff options
| -rw-r--r-- | bgpd/bgp_attr.c | 16 | ||||
| -rw-r--r-- | bgpd/bgp_attr.h | 11 | ||||
| -rw-r--r-- | bgpd/bgp_route.c | 119 | ||||
| -rw-r--r-- | lib/command.c | 20 | ||||
| -rw-r--r-- | lib/command.h | 2 | ||||
| -rw-r--r-- | lib/vty.c | 28 | ||||
| -rw-r--r-- | lib/vty.h | 7 | ||||
| -rw-r--r-- | vtysh/vtysh.c | 2 | ||||
| -rw-r--r-- | zebra/zebra_rib.c | 11 |
9 files changed, 173 insertions, 43 deletions
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index c7d7c56a12..fb7db9d57e 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -723,8 +723,10 @@ struct attr *bgp_attr_default_set(struct attr *attr, uint8_t origin) /* Create the attributes for an aggregate */ struct attr *bgp_attr_aggregate_intern(struct bgp *bgp, uint8_t origin, struct aspath *aspath, - struct community *community, int as_set, - uint8_t atomic_aggregate) + struct community *community, + struct ecommunity *ecommunity, + struct lcommunity *lcommunity, + int as_set, uint8_t atomic_aggregate) { struct attr attr; struct attr *new; @@ -760,6 +762,16 @@ struct attr *bgp_attr_aggregate_intern(struct bgp *bgp, uint8_t origin, attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES); } + if (ecommunity) { + attr.ecommunity = ecommunity; + attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES); + } + + if (lcommunity) { + attr.lcommunity = lcommunity; + attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES); + } + if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN)) { bgp_attr_add_gshut_community(&attr); } diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h index 883b129136..4c8f98947e 100644 --- a/bgpd/bgp_attr.h +++ b/bgpd/bgp_attr.h @@ -272,10 +272,13 @@ extern void bgp_attr_unintern_sub(struct attr *); extern void bgp_attr_unintern(struct attr **); extern void bgp_attr_flush(struct attr *); extern struct attr *bgp_attr_default_set(struct attr *attr, uint8_t); -extern struct attr *bgp_attr_aggregate_intern(struct bgp *, uint8_t, - struct aspath *, - struct community *, int as_set, - uint8_t); +extern struct attr *bgp_attr_aggregate_intern(struct bgp *bgp, uint8_t origin, + struct aspath *aspath, + struct community *community, + struct ecommunity *ecommunity, + struct lcommunity *lcommunity, + int as_set, + uint8_t atomic_aggregate); extern bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *, struct stream *, struct attr *, struct bpacket_attr_vec_arr *vecarr, diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index c15ce7d9aa..bb6b8aab3c 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -5482,7 +5482,9 @@ static void bgp_aggregate_free(struct bgp_aggregate *aggregate) static int bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin, struct aspath *aspath, - struct community *comm) + struct community *comm, + struct ecommunity *ecomm, + struct lcommunity *lcomm) { static struct aspath *ae = NULL; @@ -5501,6 +5503,12 @@ static int bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin, if (!community_cmp(pi->attr->community, comm)) return 0; + if (!ecommunity_cmp(pi->attr->ecommunity, ecomm)) + return 0; + + if (!lcommunity_cmp(pi->attr->lcommunity, lcomm)) + return 0; + if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)) return 0; @@ -5511,6 +5519,8 @@ static void bgp_aggregate_install(struct bgp *bgp, afi_t afi, safi_t safi, struct prefix *p, uint8_t origin, struct aspath *aspath, struct community *community, + struct ecommunity *ecommunity, + struct lcommunity *lcommunity, uint8_t atomic_aggregate, struct bgp_aggregate *aggregate) { @@ -5532,14 +5542,18 @@ static void bgp_aggregate_install(struct bgp *bgp, afi_t afi, safi_t safi, * If the aggregate information has not changed * no need to re-install it again. */ - if (bgp_aggregate_info_same(rn->info, origin, aspath, - community)) { + if (bgp_aggregate_info_same(rn->info, origin, aspath, community, + ecommunity, lcommunity)) { bgp_unlock_node(rn); if (aspath) aspath_free(aspath); if (community) community_free(community); + if (ecommunity) + ecommunity_free(&ecommunity); + if (lcommunity) + lcommunity_free(&lcommunity); return; } @@ -5550,12 +5564,14 @@ static void bgp_aggregate_install(struct bgp *bgp, afi_t afi, safi_t safi, if (pi) bgp_path_info_delete(rn, pi); - new = info_make( - ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0, bgp->peer_self, - bgp_attr_aggregate_intern(bgp, origin, aspath, - community, aggregate->as_set, - atomic_aggregate), - rn); + new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0, + bgp->peer_self, + bgp_attr_aggregate_intern(bgp, origin, aspath, + community, ecommunity, + lcommunity, + aggregate->as_set, + atomic_aggregate), + rn); SET_FLAG(new->flags, BGP_PATH_VALID); bgp_path_info_add(rn, new); @@ -5591,6 +5607,10 @@ static void bgp_aggregate_route(struct bgp *bgp, struct prefix *p, struct aspath *asmerge = NULL; struct community *community = NULL; struct community *commerge = NULL; + struct ecommunity *ecommunity = NULL; + struct ecommunity *ecommerge = NULL; + struct lcommunity *lcommunity = NULL; + struct lcommunity *lcommerge = NULL; struct bgp_path_info *pi; unsigned long match = 0; uint8_t atomic_aggregate = 0; @@ -5670,16 +5690,43 @@ static void bgp_aggregate_route(struct bgp *bgp, struct prefix *p, } else aspath = aspath_dup(pi->attr->aspath); - if (!pi->attr->community) - continue; + if (pi->attr->community) { + if (community) { + commerge = community_merge( + community, pi->attr->community); + community = + community_uniq_sort(commerge); + community_free(commerge); + } else + community = community_dup( + pi->attr->community); + } - if (community) { - commerge = community_merge(community, - pi->attr->community); - community = community_uniq_sort(commerge); - community_free(commerge); - } else - community = community_dup(pi->attr->community); + if (pi->attr->ecommunity) { + if (ecommunity) { + ecommerge = ecommunity_merge( + ecommunity, + pi->attr->ecommunity); + ecommunity = + ecommunity_uniq_sort(ecommerge); + ecommunity_free(&ecommerge); + } else + ecommunity = ecommunity_dup( + pi->attr->ecommunity); + } + + if (pi->attr->lcommunity) { + if (lcommunity) { + lcommerge = lcommunity_merge( + lcommunity, + pi->attr->lcommunity); + lcommunity = + lcommunity_uniq_sort(lcommerge); + lcommunity_free(&lcommerge); + } else + lcommunity = lcommunity_dup( + pi->attr->lcommunity); + } } if (match) bgp_process(bgp, rn, afi, safi); @@ -5716,17 +5763,48 @@ static void bgp_aggregate_route(struct bgp *bgp, struct prefix *p, community = community_dup( pinew->attr->community); } + + if (pinew->attr->ecommunity) { + if (ecommunity) { + ecommerge = ecommunity_merge( + ecommunity, + pinew->attr->ecommunity); + ecommunity = + ecommunity_uniq_sort(ecommerge); + ecommunity_free(&ecommerge); + } else + ecommunity = ecommunity_dup( + pinew->attr->ecommunity); + } + + if (pinew->attr->lcommunity) { + if (lcommunity) { + lcommerge = lcommunity_merge( + lcommunity, + pinew->attr->lcommunity); + lcommunity = + lcommunity_uniq_sort(lcommerge); + lcommunity_free(&lcommerge); + } else + lcommunity = lcommunity_dup( + pinew->attr->lcommunity); + } } } bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community, - atomic_aggregate, aggregate); + ecommunity, lcommunity, atomic_aggregate, + aggregate); if (aggregate->count == 0) { if (aspath) aspath_free(aspath); if (community) community_free(community); + if (ecommunity) + ecommunity_free(&ecommunity); + if (lcommunity) + lcommunity_free(&lcommunity); } } @@ -5871,7 +5949,8 @@ static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str, aggregate = bgp_aggregate_get_node_info(rn); bgp_aggregate_delete(bgp, &p, afi, safi, aggregate); - bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL, 0, aggregate); + bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL, + NULL, NULL, 0, aggregate); /* Unlock aggregate address configuration. */ bgp_aggregate_set_node_info(rn, NULL); diff --git a/lib/command.c b/lib/command.c index 60c5f4e75b..6fe4ae2d8f 100644 --- a/lib/command.c +++ b/lib/command.c @@ -1281,7 +1281,8 @@ int cmd_execute(struct vty *vty, const char *cmd, * as to why no command could be executed. */ int command_config_read_one_line(struct vty *vty, - const struct cmd_element **cmd, int use_daemon) + const struct cmd_element **cmd, + uint32_t line_num, int use_daemon) { vector vline; int saved_node; @@ -1322,8 +1323,16 @@ int command_config_read_one_line(struct vty *vty, } } - if (ret != CMD_SUCCESS && ret != CMD_WARNING) - memcpy(vty->error_buf, vty->buf, VTY_BUFSIZ); + if (ret != CMD_SUCCESS && ret != CMD_WARNING) { + struct vty_error *ve = XCALLOC(MTYPE_TMP, sizeof(*ve)); + + memcpy(ve->error_buf, vty->buf, VTY_BUFSIZ); + ve->line_num = line_num; + if (!vty->error) + vty->error = list_new(); + + listnode_add(vty->error, ve); + } cmd_free_strvec(vline); @@ -1337,10 +1346,9 @@ int config_from_file(struct vty *vty, FILE *fp, unsigned int *line_num) *line_num = 0; while (fgets(vty->buf, VTY_BUFSIZ, fp)) { - if (!error_ret) - ++(*line_num); + ++(*line_num); - ret = command_config_read_one_line(vty, NULL, 0); + ret = command_config_read_one_line(vty, NULL, *line_num, 0); if (ret != CMD_SUCCESS && ret != CMD_WARNING && ret != CMD_ERR_NOTHING_TODO) diff --git a/lib/command.h b/lib/command.h index 8e51641b88..fbff1e67f4 100644 --- a/lib/command.h +++ b/lib/command.h @@ -419,7 +419,7 @@ extern char **cmd_complete_command(vector, struct vty *, int *status); extern const char *cmd_prompt(enum node_type); extern int command_config_read_one_line(struct vty *vty, const struct cmd_element **, - int use_config_node); + uint32_t line_num, int use_config_node); extern int config_from_file(struct vty *, FILE *, unsigned int *line_num); extern enum node_type node_parent(enum node_type); /* @@ -1695,7 +1695,6 @@ struct vty *vty_new() new->lbuf = buffer_new(0); new->obuf = buffer_new(0); /* Use default buffer size. */ new->buf = XCALLOC(MTYPE_VTY, VTY_BUFSIZ); - new->error_buf = XCALLOC(MTYPE_VTY, VTY_BUFSIZ); new->max = VTY_BUFSIZ; return new; @@ -2278,6 +2277,13 @@ void vty_serv_sock(const char *addr, unsigned short port, const char *path) #endif /* VTYSH */ } +static void vty_error_delete(void *arg) +{ + struct vty_error *ve = arg; + + XFREE(MTYPE_TMP, ve); +} + /* Close vty interface. Warning: call this only from functions that will be careful not to access the vty afterwards (since it has now been freed). This is safest from top-level functions (called @@ -2329,8 +2335,10 @@ void vty_close(struct vty *vty) if (vty->buf) XFREE(MTYPE_VTY, vty->buf); - if (vty->error_buf) - XFREE(MTYPE_VTY, vty->error_buf); + if (vty->error) { + vty->error->del = vty_error_delete; + list_delete(&vty->error); + } /* Check configure. */ vty_config_unlock(vty); @@ -2368,6 +2376,8 @@ static void vty_read_file(FILE *confp) { int ret; struct vty *vty; + struct vty_error *ve; + struct listnode *node; unsigned int line_num = 0; vty = vty_new(); @@ -2417,11 +2427,13 @@ static void vty_read_file(FILE *confp) break; } - nl = strchr(vty->error_buf, '\n'); - if (nl) - *nl = '\0'; - flog_err(EC_LIB_VTY, "ERROR: %s on config line %u: %s", message, - line_num, vty->error_buf); + for (ALL_LIST_ELEMENTS_RO(vty->error, node, ve)) { + nl = strchr(ve->error_buf, '\n'); + if (nl) + *nl = '\0'; + flog_err(EC_LIB_VTY, "ERROR: %s on config line %u: %s", + message, ve->line_num, ve->error_buf); + } } vty_close(vty); @@ -33,6 +33,11 @@ #define VTY_BUFSIZ 4096 #define VTY_MAXHIST 20 +struct vty_error { + char error_buf[VTY_BUFSIZ]; + uint32_t line_num; +}; + /* VTY struct. */ struct vty { /* File descripter of this vty. */ @@ -71,7 +76,7 @@ struct vty { char *buf; /* Command input error buffer */ - char *error_buf; + struct list *error; /* Command cursor point */ int cp; diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index 6a92b90813..8ed11f1876 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -856,7 +856,7 @@ int vtysh_config_from_file(struct vty *vty, FILE *fp) while (fgets(vty->buf, VTY_BUFSIZ, fp)) { lineno++; - ret = command_config_read_one_line(vty, &cmd, 1); + ret = command_config_read_one_line(vty, &cmd, lineno, 1); switch (ret) { case CMD_WARNING: diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 4c35b1003f..05419ee4bf 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -601,9 +601,20 @@ static int nexthop_active(afi_t afi, struct route_entry *re, __PRETTY_FUNCTION__); return resolved; } else { + if (IS_ZEBRA_DEBUG_RIB_DETAILED) { + zlog_debug("\t%s: Route Type %s has not turned on recursion", + __PRETTY_FUNCTION__, + zebra_route_string(re->type)); + if (re->type == ZEBRA_ROUTE_BGP && + !CHECK_FLAG(re->flags, ZEBRA_FLAG_IBGP)) + zlog_debug("\tEBGP: see \"disable-ebgp-connected-route-check\" or \"disable-connected-check\""); + } return 0; } } + if (IS_ZEBRA_DEBUG_RIB_DETAILED) + zlog_debug("\t%s: Nexthop did not lookup in table", + __PRETTY_FUNCTION__); return 0; } |
