From 873d76e7f9b4a803c92dc44bc92ef5565e74ca8e Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 20 Oct 2016 21:20:15 -0400 Subject: [PATCH 1/5] lib: Fix for int64 and json on some systems When compiling json on systems with json/json.h that don't have json_object_new_int64, just use json_object_new_int instead and accept we might truncate data. Signed-off-by: Donald Sharp --- lib/json.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/json.c b/lib/json.c index ca30c60984..c49a4f9074 100644 --- a/lib/json.c +++ b/lib/json.c @@ -56,7 +56,11 @@ json_object_int_add(struct json_object* obj, const char *key, int32_t i) void json_object_long_add(struct json_object* obj, const char *key, int64_t i) { +#if defined(HAVE_JSON_C_JSON_H) json_object_object_add(obj, key, json_object_new_int64(i)); +#else + json_object_object_add(obj, key, json_object_new_int((int)i)); +#endif } void From 9d2ea6080219372f620ee467c27e347914ef932b Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 21 Oct 2016 09:14:41 -0400 Subject: [PATCH 2/5] vtysh: Fix 'show run' output of bgp The code in vtysh was incorrectly handling sub-modes for a bgp config when doing a 'show run' This commit: commit 65efcfce427e2abb548874ebb1a11a3b2ee7bc17 Author: Lou Berger Date: Sat May 7 14:18:56 2016 -0400 bgpd: add L3/L2VPN Virtual Network Control feature Added vnc support to the bgp daemon. In addition it modified vtysh_config.c to help vtysh understand bgp sub-modes. This caused the output of the show run bgp command to be displayed incorrectly: router bgp 65001 ! address-family ipv4 unicast maximum-paths 4 exit-address-family ! ! address-family ipv6 unicast maximum-paths 3 exit-address-family ! Backing out this change allows vtysh to have the correct display of bgp now. Ticket: CM-13136 Signed-off-by: Donald Sharp Reviewed-by: Daniel Walton Reviewed-by: David Lamparter --- vtysh/vtysh_config.c | 35 ++++------------------------------- 1 file changed, 4 insertions(+), 31 deletions(-) diff --git a/vtysh/vtysh_config.c b/vtysh/vtysh_config.c index 67fc0d77bf..7ad457ee7b 100644 --- a/vtysh/vtysh_config.c +++ b/vtysh/vtysh_config.c @@ -171,37 +171,10 @@ vtysh_config_parse_line (const char *line) /* Store line to current configuration. */ if (config) { - if (strncmp (line, " address-family vpnv4", - strlen (" address-family vpnv4")) == 0) - config = config_get (BGP_VPNV4_NODE, line); - else if (strncmp (line, " address-family vpn6", - strlen (" address-family vpn6")) == 0) - config = config_get (BGP_VPNV6_NODE, line); - else if (strncmp (line, " address-family encapv6", - strlen (" address-family encapv6")) == 0) - config = config_get (BGP_ENCAPV6_NODE, line); - else if (strncmp (line, " address-family encap", - strlen (" address-family encap")) == 0) - config = config_get (BGP_ENCAP_NODE, line); - else if (strncmp (line, " address-family ipv4 multicast", - strlen (" address-family ipv4 multicast")) == 0) - config = config_get (BGP_IPV4M_NODE, line); - else if (strncmp (line, " address-family ipv6", - strlen (" address-family ipv6")) == 0) - config = config_get (BGP_IPV6_NODE, line); - else if (strncmp (line, " vnc defaults", - strlen (" vnc defaults")) == 0) - config = config_get (BGP_VNC_DEFAULTS_NODE, line); - else if (strncmp (line, " vnc nve-group", - strlen (" vnc nve-group")) == 0) - config = config_get (BGP_VNC_NVE_GROUP_NODE, line); - else if (strncmp (line, " vnc l2-group", - strlen (" vnc l2-group")) == 0) - config = config_get (BGP_VNC_L2_GROUP_NODE, line); - else if (config->index == RMAP_NODE || - config->index == INTERFACE_NODE || - config->index == NS_NODE || - config->index == VTY_NODE) + if (config->index == RMAP_NODE || + config->index == INTERFACE_NODE || + config->index == NS_NODE || + config->index == VTY_NODE) config_add_line_uniq (config->line, line); else config_add_line (config->line, line); From 9408259a54093b395e5798068a5b4cd0d32be97f Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 21 Oct 2016 10:20:39 -0400 Subject: [PATCH 3/5] bgpd: Fix duplicate installs of rfapi commands When installing commands into the parser, don't duplicate the enable/view nodes. Signed-off-by: Donald Sharp --- bgpd/rfapi/rfapi_vty.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/bgpd/rfapi/rfapi_vty.c b/bgpd/rfapi/rfapi_vty.c index 1978bec280..c198564d10 100644 --- a/bgpd/rfapi/rfapi_vty.c +++ b/bgpd/rfapi/rfapi_vty.c @@ -4983,34 +4983,21 @@ void rfapi_vty_init () install_element (ENABLE_NODE, &vnc_clear_counters_cmd); install_element (VIEW_NODE, &vnc_show_summary_cmd); - install_element (ENABLE_NODE, &vnc_show_summary_cmd); install_element (VIEW_NODE, &vnc_show_nves_cmd); - install_element (ENABLE_NODE, &vnc_show_nves_cmd); install_element (VIEW_NODE, &vnc_show_nves_ptct_cmd); - install_element (ENABLE_NODE, &vnc_show_nves_ptct_cmd); install_element (VIEW_NODE, &vnc_show_registrations_cmd); - install_element (ENABLE_NODE, &vnc_show_registrations_cmd); install_element (VIEW_NODE, &vnc_show_registrations_pfx_cmd); - install_element (ENABLE_NODE, &vnc_show_registrations_pfx_cmd); install_element (VIEW_NODE, &vnc_show_registrations_some_cmd); - install_element (ENABLE_NODE, &vnc_show_registrations_some_cmd); install_element (VIEW_NODE, &vnc_show_registrations_some_pfx_cmd); - install_element (ENABLE_NODE, &vnc_show_registrations_some_pfx_cmd); install_element (VIEW_NODE, &vnc_show_responses_cmd); - install_element (ENABLE_NODE, &vnc_show_responses_cmd); install_element (VIEW_NODE, &vnc_show_responses_pfx_cmd); - install_element (ENABLE_NODE, &vnc_show_responses_pfx_cmd); install_element (VIEW_NODE, &vnc_show_responses_some_cmd); - install_element (ENABLE_NODE, &vnc_show_responses_some_cmd); install_element (VIEW_NODE, &vnc_show_responses_some_pfx_cmd); - install_element (ENABLE_NODE, &vnc_show_responses_some_pfx_cmd); - install_element (ENABLE_NODE, &show_vnc_queries_cmd); install_element (VIEW_NODE, &show_vnc_queries_cmd); - install_element (ENABLE_NODE, &show_vnc_queries_pfx_cmd); install_element (VIEW_NODE, &show_vnc_queries_pfx_cmd); } From ea8a98255882c7abefb336fb7d7fa03e987a787e Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 21 Oct 2016 10:42:42 -0400 Subject: [PATCH 4/5] bgpd: Fix rfapi qobj use. We need to tell the system that we've initialized the qobj memory. Signed-off-by: Donald Sharp Reviewed-by: David Lamparter --- bgpd/rfapi/bgp_rfapi_cfg.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/bgpd/rfapi/bgp_rfapi_cfg.c b/bgpd/rfapi/bgp_rfapi_cfg.c index 9e4eafa6cf..d064c50d8c 100644 --- a/bgpd/rfapi/bgp_rfapi_cfg.c +++ b/bgpd/rfapi/bgp_rfapi_cfg.c @@ -623,7 +623,12 @@ rfapi_group_lookup_byname (struct bgp *bgp, const char *name) static struct rfapi_nve_group_cfg * rfapi_group_new () { - return XCALLOC (MTYPE_RFAPI_GROUP_CFG, sizeof (struct rfapi_nve_group_cfg)); + struct rfapi_nve_group_cfg *rfg; + + rfg = XCALLOC (MTYPE_RFAPI_GROUP_CFG, sizeof (struct rfapi_nve_group_cfg)); + QOBJ_REG (rfg, rfapi_nve_group_cfg); + + return rfg; } static struct rfapi_l2_group_cfg * @@ -646,12 +651,18 @@ rfapi_l2_group_lookup_byname (struct bgp *bgp, const char *name) static struct rfapi_l2_group_cfg * rfapi_l2_group_new () { - return XCALLOC (MTYPE_RFAPI_L2_CFG, sizeof (struct rfapi_l2_group_cfg)); + struct rfapi_l2_group_cfg *rfg; + + rfg = XCALLOC (MTYPE_RFAPI_L2_CFG, sizeof (struct rfapi_l2_group_cfg)); + QOBJ_REG (rfg, rfapi_l2_group_cfg); + + return rfg; } static void rfapi_l2_group_del (struct rfapi_l2_group_cfg *rfg) { + QOBJ_UNREG (rfg); XFREE (MTYPE_RFAPI_L2_CFG, rfg); } @@ -2752,6 +2763,7 @@ bgp_rfapi_delete_nve_group ( XFREE (MTYPE_RFAPI_RFP_GROUP_CFG, rfg->rfp_cfg); listnode_delete (bgp->rfapi_cfg->nve_groups_sequential, rfg); + QOBJ_UNREG (rfg); XFREE (MTYPE_RFAPI_GROUP_CFG, rfg); /* From aac9ef6cb0169ea96debe2872066021608631c16 Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Fri, 21 Oct 2016 17:51:05 +0000 Subject: [PATCH 5/5] bgpd: add 'neighbor x.x.x.x allowas-in origin' knob Signed-off-by: Daniel Walton Reviewed-by: Don Slice Ticket: CM-13207 normal table on spine-1....we do not see 6.0.0.10 (spine-2's loopback) spine-1 and spine-2 are in AS 65200 superm-redxp-05# show ip bgp BGP table version is 13, local router ID is 6.0.0.9 Status codes: s suppressed, d damped, h history, * valid, > best, = multipath, i internal, r RIB-failure, S Stale, R Removed Origin codes: i - IGP, e - EGP, ? - incomplete Network Next Hop Metric LocPrf Weight Path *> 6.0.0.5/32 swp1 0 0 65101 ? *> 6.0.0.6/32 swp2 0 0 65101 ? *> 6.0.0.7/32 swp3 0 0 65104 ? *> 6.0.0.8/32 swp4 0 0 65104 ? *> 6.0.0.9/32 0.0.0.0 0 32768 ? *= 6.0.0.11/32 swp2 0 65101 65001 ? *> swp1 0 65101 65001 ? *= 6.0.0.12/32 swp2 0 65101 65002 ? *> swp1 0 65101 65002 ? *= 6.0.0.13/32 swp4 0 65104 65001 ? *> swp3 0 65104 65001 ? *= 6.0.0.14/32 swp4 0 65104 65002 ? *> swp3 0 65104 65002 ? Displayed 9 out of 13 total prefixes superm-redxp-05# spine-1 with "neighbor x.x.x.x allowas-in origin", we now see 6.0.0.10 superm-redxp-05# show ip bgp BGP table version is 14, local router ID is 6.0.0.9 Status codes: s suppressed, d damped, h history, * valid, > best, = multipath, i internal, r RIB-failure, S Stale, R Removed Origin codes: i - IGP, e - EGP, ? - incomplete Network Next Hop Metric LocPrf Weight Path *> 6.0.0.5/32 swp1 0 0 65101 ? *> 6.0.0.6/32 swp2 0 0 65101 ? *> 6.0.0.7/32 swp3 0 0 65104 ? *> 6.0.0.8/32 swp4 0 0 65104 ? * 6.0.0.9/32 swp2 0 65101 65200 ? * swp1 0 65101 65200 ? * swp3 0 65104 65200 ? * swp4 0 65104 65200 ? *> 0.0.0.0 0 32768 ? *= 6.0.0.10/32 swp2 0 65101 65200 ? *> swp1 0 65101 65200 ? *= swp3 0 65104 65200 ? *= swp4 0 65104 65200 ? *= 6.0.0.11/32 swp2 0 65101 65001 ? *> swp1 0 65101 65001 ? *= 6.0.0.12/32 swp2 0 65101 65002 ? *> swp1 0 65101 65002 ? *= 6.0.0.13/32 swp4 0 65104 65001 ? *> swp3 0 65104 65001 ? *= 6.0.0.14/32 swp4 0 65104 65002 ? *> swp3 0 65104 65002 ? Displayed 10 out of 21 total prefixes superm-redxp-05# The only as-paths with 65200 that made it through were the ones that originated from 65200 superm-redxp-05# show ip bgp regexp _65200_ BGP table version is 14, local router ID is 6.0.0.9 Status codes: s suppressed, d damped, h history, * valid, > best, = multipath, i internal, r RIB-failure, S Stale, R Removed Origin codes: i - IGP, e - EGP, ? - incomplete Network Next Hop Metric LocPrf Weight Path * 6.0.0.9/32 swp2 0 65101 65200 ? * swp1 0 65101 65200 ? * swp3 0 65104 65200 ? * swp4 0 65104 65200 ? *= 6.0.0.10/32 swp2 0 65101 65200 ? *> swp1 0 65101 65200 ? *= swp3 0 65104 65200 ? *= swp4 0 65104 65200 ? Displayed 2 out of 21 total prefixes superm-redxp-05# --- bgpd/bgp_aspath.c | 27 ++++++++- bgpd/bgp_aspath.h | 3 +- bgpd/bgp_route.c | 28 +++++++--- bgpd/bgp_vty.c | 22 +++++--- bgpd/bgpd.c | 140 ++++++++++++++++++++++++++++++++-------------- bgpd/bgpd.h | 3 +- 6 files changed, 161 insertions(+), 62 deletions(-) diff --git a/bgpd/bgp_aspath.c b/bgpd/bgp_aspath.c index 70d4f04935..bf1e92b26d 100644 --- a/bgpd/bgp_aspath.c +++ b/bgpd/bgp_aspath.c @@ -1163,8 +1163,8 @@ aspath_firstas_check (struct aspath *aspath, as_t asno) return 0; } -int -aspath_get_firstas (struct aspath *aspath) +unsigned int +aspath_get_first_as (struct aspath *aspath) { if (aspath == NULL || aspath->segments == NULL) return 0; @@ -1172,6 +1172,29 @@ aspath_get_firstas (struct aspath *aspath) return aspath->segments->as[0]; } +unsigned int +aspath_get_last_as (struct aspath *aspath) +{ + int i; + unsigned int last_as = 0; + const struct assegment *seg; + + if (aspath == NULL || aspath->segments == NULL) + return last_as; + + seg = aspath->segments; + + while (seg) + { + if (seg->type == AS_SEQUENCE || seg->type == AS_CONFED_SEQUENCE) + for (i = 0; i < seg->length; i++) + last_as = seg->as[i]; + seg = seg->next; + } + + return last_as; +} + /* AS path loop check. If aspath contains asno then return >= 1. */ int aspath_loop_check (struct aspath *aspath, as_t asno) diff --git a/bgpd/bgp_aspath.h b/bgpd/bgp_aspath.h index a8cc38e1cb..b15e32fec3 100644 --- a/bgpd/bgp_aspath.h +++ b/bgpd/bgp_aspath.h @@ -101,7 +101,8 @@ extern const char *aspath_print (struct aspath *); extern void aspath_print_vty (struct vty *, const char *, struct aspath *, const char *); extern void aspath_print_all_vty (struct vty *); extern unsigned int aspath_key_make (void *); -extern int aspath_get_firstas (struct aspath *); +extern unsigned int aspath_get_first_as (struct aspath *); +extern unsigned int aspath_get_last_as (struct aspath *); extern int aspath_loop_check (struct aspath *, as_t); extern int aspath_private_as_check (struct aspath *); extern int aspath_single_asn_check (struct aspath *, as_t asn); diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 44377c3692..e28aa715f9 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -1657,7 +1657,7 @@ bgp_best_selection (struct bgp *bgp, struct bgp_node *rn, { bgp_info_path_with_addpath_rx_str (new_select, path_buf); zlog_debug("%s: %s is the bestpath from AS %d", - pfx_buf, path_buf, aspath_get_firstas(new_select->attr->aspath)); + pfx_buf, path_buf, aspath_get_first_as(new_select->attr->aspath)); } } } @@ -2355,6 +2355,7 @@ bgp_update (struct peer *peer, struct prefix *p, u_int32_t addpath_id, char buf[SU_ADDRSTRLEN]; char buf2[30]; int connected = 0; + int do_loop_check = 1; #if ENABLE_BGP_VNC int vnc_implicit_withdraw = 0; #endif @@ -2390,14 +2391,23 @@ bgp_update (struct peer *peer, struct prefix *p, u_int32_t addpath_id, } } + /* If the peer is configured for "allowas-in origin" and the last ASN in the + * as-path is our ASN then we do not need to call aspath_loop_check + */ + if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN)) + if (aspath_get_last_as(attr->aspath) == bgp->as) + do_loop_check = 0; + /* AS path loop check. */ - if (aspath_loop_check (attr->aspath, bgp->as) > peer->allowas_in[afi][safi] - || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION) - && aspath_loop_check(attr->aspath, bgp->confed_id) - > peer->allowas_in[afi][safi])) + if (do_loop_check) { - reason = "as-path contains our own AS;"; - goto filtered; + if (aspath_loop_check (attr->aspath, bgp->as) > peer->allowas_in[afi][safi] + || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION) + && aspath_loop_check(attr->aspath, bgp->confed_id) > peer->allowas_in[afi][safi])) + { + reason = "as-path contains our own AS;"; + goto filtered; + } } /* Route reflector originator ID check. */ @@ -6867,7 +6877,7 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p, struct peer *peer; int addpath_capable; int has_adj; - int first_as; + unsigned int first_as; if (json_paths) { @@ -7296,7 +7306,7 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p, // Mark the bestpath(s) if (CHECK_FLAG (binfo->flags, BGP_INFO_DMED_SELECTED)) { - first_as = aspath_get_firstas(attr->aspath); + first_as = aspath_get_first_as(attr->aspath); if (json_paths) { diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 258a709837..7884d2d503 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -5863,8 +5863,9 @@ DEFUN (neighbor_allowas_in, "Accept as-path with my AS present in it\n") { int ret; + int origin = 0; struct peer *peer; - unsigned int allow_num; + int allow_num = 0; peer = peer_and_group_lookup_vty (vty, argv[0]); if (! peer) @@ -5873,21 +5874,27 @@ DEFUN (neighbor_allowas_in, if (argc == 1) allow_num = 3; else - VTY_GET_INTEGER_RANGE ("AS number", allow_num, argv[1], 1, 10); + { + if (strncmp (argv[1], "o", 1) == 0) + origin = 1; + else + VTY_GET_INTEGER_RANGE ("AS number", allow_num, argv[1], 1, 10); + } ret = peer_allowas_in_set (peer, bgp_node_afi (vty), bgp_node_safi (vty), - allow_num); + allow_num, origin); return bgp_vty_return (vty, ret); } ALIAS (neighbor_allowas_in, neighbor_allowas_in_arg_cmd, - NEIGHBOR_CMD2 "allowas-in <1-10>", + NEIGHBOR_CMD2 "allowas-in (<1-10>|origin)", NEIGHBOR_STR NEIGHBOR_ADDR_STR2 "Accept as-path with my AS present in it\n" - "Number of occurances of AS number\n") + "Number of occurances of AS number\n" + "Only accept my AS in the as-path if the route was originated in my AS\n") DEFUN (no_neighbor_allowas_in, no_neighbor_allowas_in_cmd, @@ -5911,12 +5918,13 @@ DEFUN (no_neighbor_allowas_in, ALIAS (no_neighbor_allowas_in, no_neighbor_allowas_in_val_cmd, - NO_NEIGHBOR_CMD2 "allowas-in <1-10>", + NO_NEIGHBOR_CMD2 "allowas-in (<1-10>|origin)", NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 "allow local ASN appears in aspath attribute\n" - "Number of occurances of AS number\n") + "Number of occurances of AS number\n" + "Only accept my AS in the as-path if the route was originated in my AS\n") DEFUN (neighbor_ttl_security, neighbor_ttl_security_cmd, diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index df7be41ef9..3ddb465a75 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -3668,6 +3668,7 @@ static const struct peer_flag_action peer_af_flag_action_list[] = // PEER_FLAG_DEFAULT_ORIGINATE { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out }, { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in }, + { PEER_FLAG_ALLOWAS_IN_ORIGIN, 0, peer_change_reset_in }, { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset }, { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset }, // PEER_FLAG_MAX_PREFIX @@ -4847,35 +4848,72 @@ peer_interface_unset (struct peer *peer) /* Allow-as in. */ int -peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num) +peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num, + int origin) { struct peer_group *group; struct listnode *node, *nnode; - if (allow_num < 1 || allow_num > 10) - return BGP_ERR_INVALID_VALUE; - - if (peer->allowas_in[afi][safi] != allow_num) + if (origin) { - peer->allowas_in[afi][safi] = allow_num; - SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN); - peer_on_policy_change (peer, afi, safi, 0); - } - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - return 0; - - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - if (peer->allowas_in[afi][safi] != allow_num) - { - peer->allowas_in[afi][safi] = allow_num; - SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN); + if (peer->allowas_in[afi][safi] || + CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN) || + !CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN)) + { + peer->allowas_in[afi][safi] = 0; + peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN); + peer_af_flag_set (peer, afi, safi, PEER_FLAG_ALLOWAS_IN_ORIGIN); peer_on_policy_change (peer, afi, safi, 0); - } - + } + + if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) + return 0; + + group = peer->group; + for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) + { + if (peer->allowas_in[afi][safi] || + CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN) || + !CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN)) + { + peer->allowas_in[afi][safi] = 0; + peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN); + peer_af_flag_set (peer, afi, safi, PEER_FLAG_ALLOWAS_IN_ORIGIN); + peer_on_policy_change (peer, afi, safi, 0); + } + } } + else + { + if (allow_num < 1 || allow_num > 10) + return BGP_ERR_INVALID_VALUE; + + if (peer->allowas_in[afi][safi] != allow_num || + CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN)) + { + peer->allowas_in[afi][safi] = allow_num; + peer_af_flag_set (peer, afi, safi, PEER_FLAG_ALLOWAS_IN); + peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN_ORIGIN); + peer_on_policy_change (peer, afi, safi, 0); + } + + if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) + return 0; + + group = peer->group; + for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) + { + if (peer->allowas_in[afi][safi] != allow_num || + CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN)) + { + peer->allowas_in[afi][safi] = allow_num; + peer_af_flag_set (peer, afi, safi, PEER_FLAG_ALLOWAS_IN); + peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN_ORIGIN); + peer_on_policy_change (peer, afi, safi, 0); + } + } + } + return 0; } @@ -4885,10 +4923,12 @@ peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi) struct peer_group *group; struct listnode *node, *nnode; - if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN)) + if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN) || + CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN)) { peer->allowas_in[afi][safi] = 0; peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN); + peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN_ORIGIN); peer_on_policy_change (peer, afi, safi, 0); } @@ -4898,10 +4938,12 @@ peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi) group = peer->group; for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) { - if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN)) + if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN) || + CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN)) { peer->allowas_in[afi][safi] = 0; peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN); + peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN_ORIGIN); peer_on_policy_change (peer, afi, safi, 0); } } @@ -7001,25 +7043,39 @@ bgp_config_write_peer_af (struct vty *vty, struct bgp *bgp, addr, VTY_NEWLINE); } - /* Allow AS in. */ + /* allowas-in <1-10> */ if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN)) - if (! peer_group_active (peer) - || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN) - || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi]) - { - if (peer->allowas_in[afi][safi] == 3) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s allowas-in%s", - addr, VTY_NEWLINE); - } - else - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s allowas-in %d%s", - addr, peer->allowas_in[afi][safi], VTY_NEWLINE); - } - } + { + if (! peer_group_active (peer) + || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN) + || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi]) + { + if (peer->allowas_in[afi][safi] == 3) + { + afi_header_vty_out (vty, afi, safi, write, + " neighbor %s allowas-in%s", + addr, VTY_NEWLINE); + } + else + { + afi_header_vty_out (vty, afi, safi, write, + " neighbor %s allowas-in %d%s", + addr, peer->allowas_in[afi][safi], VTY_NEWLINE); + } + } + } + + /* allowas-in origin */ + else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN_ORIGIN)) + { + if (! peer_group_active (peer) + || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN_ORIGIN)) + { + afi_header_vty_out (vty, afi, safi, write, + " neighbor %s allowas-in origin%s", + addr, VTY_NEWLINE); + } + } /* weight */ if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_WEIGHT)) diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index f6e8598494..dd6a0fdccf 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -698,6 +698,7 @@ struct peer #define PEER_FLAG_ADDPATH_TX_ALL_PATHS (1 << 22) /* addpath-tx-all-paths */ #define PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS (1 << 23) /* addpath-tx-bestpath-per-AS */ #define PEER_FLAG_WEIGHT (1 << 24) /* weight */ +#define PEER_FLAG_ALLOWAS_IN_ORIGIN (1 << 25) /* allowas-in origin */ /* MD5 password */ char *password; @@ -1312,7 +1313,7 @@ extern void peer_interface_unset (struct peer *); extern int peer_distribute_set (struct peer *, afi_t, safi_t, int, const char *); extern int peer_distribute_unset (struct peer *, afi_t, safi_t, int); -extern int peer_allowas_in_set (struct peer *, afi_t, safi_t, int); +extern int peer_allowas_in_set (struct peer *, afi_t, safi_t, int, int); extern int peer_allowas_in_unset (struct peer *, afi_t, safi_t); extern int peer_local_as_set (struct peer *, as_t, int, int);