diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index afb37aeef6..44377c3692 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -13995,7 +13995,7 @@ ALIAS (show_bgp_instance_neighbor_damp, #endif /* HAVE_IPV6 */ -struct bgp_table *bgp_distance_table; +struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX]; struct bgp_distance { @@ -14023,12 +14023,17 @@ bgp_distance_set (struct vty *vty, const char *distance_str, const char *ip_str, const char *access_list_str) { int ret; - struct prefix_ipv4 p; + afi_t afi; + safi_t safi; + struct prefix p; u_char distance; struct bgp_node *rn; struct bgp_distance *bdistance; - ret = str2prefix_ipv4 (ip_str, &p); + afi = bgp_node_afi (vty); + safi = bgp_node_safi (vty); + + ret = str2prefix (ip_str, &p); if (ret == 0) { vty_out (vty, "Malformed prefix%s", VTY_NEWLINE); @@ -14038,7 +14043,7 @@ bgp_distance_set (struct vty *vty, const char *distance_str, distance = atoi (distance_str); /* Get BGP distance node. */ - rn = bgp_node_get (bgp_distance_table, (struct prefix *) &p); + rn = bgp_node_get (bgp_distance_table[afi][safi], (struct prefix *) &p); if (rn->info) { bdistance = rn->info; @@ -14070,19 +14075,24 @@ bgp_distance_unset (struct vty *vty, const char *distance_str, const char *ip_str, const char *access_list_str) { int ret; + afi_t afi; + safi_t safi; + struct prefix p; int distance; - struct prefix_ipv4 p; struct bgp_node *rn; struct bgp_distance *bdistance; - ret = str2prefix_ipv4 (ip_str, &p); + afi = bgp_node_afi (vty); + safi = bgp_node_safi (vty); + + ret = str2prefix (ip_str, &p); if (ret == 0) { vty_out (vty, "Malformed prefix%s", VTY_NEWLINE); return CMD_WARNING; } - rn = bgp_node_lookup (bgp_distance_table, (struct prefix *)&p); + rn = bgp_node_lookup (bgp_distance_table[afi][safi], (struct prefix *)&p); if (! rn) { vty_out (vty, "Can't find specified prefix%s", VTY_NEWLINE); @@ -14111,10 +14121,11 @@ bgp_distance_unset (struct vty *vty, const char *distance_str, /* Apply BGP information to distance method. */ u_char -bgp_distance_apply (struct prefix *p, struct bgp_info *rinfo, struct bgp *bgp) +bgp_distance_apply (struct prefix *p, struct bgp_info *rinfo, afi_t afi, + safi_t safi, struct bgp *bgp) { struct bgp_node *rn; - struct prefix_ipv4 q; + struct prefix q; struct peer *peer; struct bgp_distance *bdistance; struct access_list *alist; @@ -14123,21 +14134,11 @@ bgp_distance_apply (struct prefix *p, struct bgp_info *rinfo, struct bgp *bgp) if (! bgp) return 0; - if (p->family != AF_INET) - return 0; - peer = rinfo->peer; - if (peer->su.sa.sa_family != AF_INET) - return 0; - - memset (&q, 0, sizeof (struct prefix_ipv4)); - q.family = AF_INET; - q.prefix = peer->su.sin.sin_addr; - q.prefixlen = IPV4_MAX_BITLEN; - /* Check source address. */ - rn = bgp_node_match (bgp_distance_table, (struct prefix *) &q); + sockunion2hostprefix (&peer->su, &q); + rn = bgp_node_match (bgp_distance_table[afi][safi], &q); if (rn) { bdistance = rn->info; @@ -14145,7 +14146,7 @@ bgp_distance_apply (struct prefix *p, struct bgp_info *rinfo, struct bgp *bgp) if (bdistance->access_list) { - alist = access_list_lookup (AFI_IP, bdistance->access_list); + alist = access_list_lookup (afi, bdistance->access_list); if (alist && access_list_apply (alist, p) == FILTER_PERMIT) return bdistance->distance; } @@ -14154,7 +14155,7 @@ bgp_distance_apply (struct prefix *p, struct bgp_info *rinfo, struct bgp *bgp) } /* Backdoor check. */ - rn = bgp_node_lookup (bgp->route[AFI_IP][SAFI_UNICAST], p); + rn = bgp_node_lookup (bgp->route[afi][safi], p); if (rn) { bgp_static = rn->info; @@ -14162,8 +14163,8 @@ bgp_distance_apply (struct prefix *p, struct bgp_info *rinfo, struct bgp *bgp) if (bgp_static->backdoor) { - if (bgp->distance_local) - return bgp->distance_local; + if (bgp->distance_local[afi][safi]) + return bgp->distance_local[afi][safi]; else return ZEBRA_IBGP_DISTANCE_DEFAULT; } @@ -14171,14 +14172,14 @@ bgp_distance_apply (struct prefix *p, struct bgp_info *rinfo, struct bgp *bgp) if (peer->sort == BGP_PEER_EBGP) { - if (bgp->distance_ebgp) - return bgp->distance_ebgp; + if (bgp->distance_ebgp[afi][safi]) + return bgp->distance_ebgp[afi][safi]; return ZEBRA_EBGP_DISTANCE_DEFAULT; } else { - if (bgp->distance_ibgp) - return bgp->distance_ibgp; + if (bgp->distance_ibgp[afi][safi]) + return bgp->distance_ibgp[afi][safi]; return ZEBRA_IBGP_DISTANCE_DEFAULT; } } @@ -14193,12 +14194,16 @@ DEFUN (bgp_distance, "Distance for local routes\n") { struct bgp *bgp; + afi_t afi; + safi_t safi; bgp = vty->index; + afi = bgp_node_afi (vty); + safi = bgp_node_safi (vty); - bgp->distance_ebgp = atoi (argv[0]); - bgp->distance_ibgp = atoi (argv[1]); - bgp->distance_local = atoi (argv[2]); + bgp->distance_ebgp[afi][safi] = atoi (argv[0]); + bgp->distance_ibgp[afi][safi] = atoi (argv[1]); + bgp->distance_local[afi][safi] = atoi (argv[2]); return CMD_SUCCESS; } @@ -14213,12 +14218,16 @@ DEFUN (no_bgp_distance, "Distance for local routes\n") { struct bgp *bgp; + afi_t afi; + safi_t safi; bgp = vty->index; + afi = bgp_node_afi (vty); + safi = bgp_node_safi (vty); - bgp->distance_ebgp= 0; - bgp->distance_ibgp = 0; - bgp->distance_local = 0; + bgp->distance_ebgp[afi][safi] = 0; + bgp->distance_ibgp[afi][safi] = 0; + bgp->distance_local[afi][safi] = 0; return CMD_SUCCESS; } @@ -14277,6 +14286,54 @@ DEFUN (no_bgp_distance_source_access_list, return CMD_SUCCESS; } +DEFUN (ipv6_bgp_distance_source, + ipv6_bgp_distance_source_cmd, + "distance <1-255> X:X::X:X/M", + "Define an administrative distance\n" + "Administrative distance\n" + "IP source prefix\n") +{ + bgp_distance_set (vty, argv[0], argv[1], NULL); + return CMD_SUCCESS; +} + +DEFUN (no_ipv6_bgp_distance_source, + no_ipv6_bgp_distance_source_cmd, + "no distance <1-255> X:X::X:X/M", + NO_STR + "Define an administrative distance\n" + "Administrative distance\n" + "IP source prefix\n") +{ + bgp_distance_unset (vty, argv[0], argv[1], NULL); + return CMD_SUCCESS; +} + +DEFUN (ipv6_bgp_distance_source_access_list, + ipv6_bgp_distance_source_access_list_cmd, + "distance <1-255> X:X::X:X/M WORD", + "Define an administrative distance\n" + "Administrative distance\n" + "IP source prefix\n" + "Access list name\n") +{ + bgp_distance_set (vty, argv[0], argv[1], argv[2]); + return CMD_SUCCESS; +} + +DEFUN (no_ipv6_bgp_distance_source_access_list, + no_ipv6_bgp_distance_source_access_list_cmd, + "no distance <1-255> X:X::X:X/M WORD", + NO_STR + "Define an administrative distance\n" + "Administrative distance\n" + "IP source prefix\n" + "Access list name\n") +{ + bgp_distance_unset (vty, argv[0], argv[1], argv[2]); + return CMD_SUCCESS; +} + DEFUN (bgp_damp_set, bgp_damp_set_cmd, "bgp dampening <1-45> <1-20000> <1-20000> <1-255>", @@ -14711,40 +14768,53 @@ bgp_config_write_network (struct vty *vty, struct bgp *bgp, } int -bgp_config_write_distance (struct vty *vty, struct bgp *bgp) +bgp_config_write_distance (struct vty *vty, struct bgp *bgp, afi_t afi, + safi_t safi, int *write) { struct bgp_node *rn; struct bgp_distance *bdistance; /* Distance configuration. */ - if (bgp->distance_ebgp - && bgp->distance_ibgp - && bgp->distance_local - && (bgp->distance_ebgp != ZEBRA_EBGP_DISTANCE_DEFAULT - || bgp->distance_ibgp != ZEBRA_IBGP_DISTANCE_DEFAULT - || bgp->distance_local != ZEBRA_IBGP_DISTANCE_DEFAULT)) - vty_out (vty, " distance bgp %d %d %d%s", - bgp->distance_ebgp, bgp->distance_ibgp, bgp->distance_local, - VTY_NEWLINE); - - for (rn = bgp_table_top (bgp_distance_table); rn; rn = bgp_route_next (rn)) + if (bgp->distance_ebgp[afi][safi] + && bgp->distance_ibgp[afi][safi] + && bgp->distance_local[afi][safi] + && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT + || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT + || bgp->distance_local[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT)) + { + bgp_config_write_family_header (vty, afi, safi, write); + vty_out (vty, " distance bgp %d %d %d%s", + bgp->distance_ebgp[afi][safi], bgp->distance_ibgp[afi][safi], + bgp->distance_local[afi][safi], VTY_NEWLINE); + } + + for (rn = bgp_table_top (bgp_distance_table[afi][safi]); rn; + rn = bgp_route_next (rn)) if ((bdistance = rn->info) != NULL) { - vty_out (vty, " distance %d %s/%d %s%s", bdistance->distance, - inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen, + char buf[PREFIX_STRLEN]; + + bgp_config_write_family_header (vty, afi, safi, write); + vty_out (vty, " distance %d %s %s%s", bdistance->distance, + prefix2str (&rn->p, buf, sizeof (buf)), bdistance->access_list ? bdistance->access_list : "", VTY_NEWLINE); } - return 0; + return *write; } /* Allocate routing table structure and install commands. */ void bgp_route_init (void) { + afi_t afi; + safi_t safi; + /* Init BGP distance table. */ - bgp_distance_table = bgp_table_init (AFI_IP, SAFI_UNICAST); + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) + bgp_distance_table[afi][safi] = bgp_table_init (afi, safi); /* IPv4 BGP commands. */ install_element (BGP_NODE, &bgp_table_map_cmd); @@ -15178,6 +15248,34 @@ bgp_route_init (void) install_element (BGP_NODE, &no_bgp_distance_source_cmd); install_element (BGP_NODE, &bgp_distance_source_access_list_cmd); install_element (BGP_NODE, &no_bgp_distance_source_access_list_cmd); + install_element (BGP_IPV4_NODE, &bgp_distance_cmd); + install_element (BGP_IPV4_NODE, &no_bgp_distance_cmd); + install_element (BGP_IPV4_NODE, &no_bgp_distance2_cmd); + install_element (BGP_IPV4_NODE, &bgp_distance_source_cmd); + install_element (BGP_IPV4_NODE, &no_bgp_distance_source_cmd); + install_element (BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd); + install_element (BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd); + install_element (BGP_IPV4M_NODE, &bgp_distance_cmd); + install_element (BGP_IPV4M_NODE, &no_bgp_distance_cmd); + install_element (BGP_IPV4M_NODE, &no_bgp_distance2_cmd); + install_element (BGP_IPV4M_NODE, &bgp_distance_source_cmd); + install_element (BGP_IPV4M_NODE, &no_bgp_distance_source_cmd); + install_element (BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd); + install_element (BGP_IPV4M_NODE, &no_bgp_distance_source_access_list_cmd); + install_element (BGP_IPV6_NODE, &bgp_distance_cmd); + install_element (BGP_IPV6_NODE, &no_bgp_distance_cmd); + install_element (BGP_IPV6_NODE, &no_bgp_distance2_cmd); + install_element (BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd); + install_element (BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd); + install_element (BGP_IPV6_NODE, &ipv6_bgp_distance_source_access_list_cmd); + install_element (BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_access_list_cmd); + install_element (BGP_IPV6M_NODE, &bgp_distance_cmd); + install_element (BGP_IPV6M_NODE, &no_bgp_distance_cmd); + install_element (BGP_IPV6M_NODE, &no_bgp_distance2_cmd); + install_element (BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd); + install_element (BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd); + install_element (BGP_IPV6M_NODE, &ipv6_bgp_distance_source_access_list_cmd); + install_element (BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_access_list_cmd); install_element (BGP_NODE, &bgp_damp_set_cmd); install_element (BGP_NODE, &bgp_damp_set2_cmd); @@ -15203,6 +15301,13 @@ bgp_route_init (void) void bgp_route_finish (void) { - bgp_table_unlock (bgp_distance_table); - bgp_distance_table = NULL; + afi_t afi; + safi_t safi; + + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) + { + bgp_table_unlock (bgp_distance_table[afi][safi]); + bgp_distance_table[afi][safi] = NULL; + } } diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index 0dce5da572..bb06204689 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -307,14 +307,14 @@ extern void bgp_add_eoiu_mark (struct bgp *); extern int bgp_config_write_table_map (struct vty *, struct bgp *, afi_t, safi_t, int *); extern int bgp_config_write_network (struct vty *, struct bgp *, afi_t, safi_t, int *); -extern int bgp_config_write_distance (struct vty *, struct bgp *); +extern int bgp_config_write_distance (struct vty *, struct bgp *, afi_t, safi_t, int *); extern void bgp_aggregate_increment (struct bgp *, struct prefix *, struct bgp_info *, afi_t, safi_t); extern void bgp_aggregate_decrement (struct bgp *, struct prefix *, struct bgp_info *, afi_t, safi_t); -extern u_char bgp_distance_apply (struct prefix *, struct bgp_info *, struct bgp *); +extern u_char bgp_distance_apply (struct prefix *, struct bgp_info *, afi_t, safi_t, struct bgp *); extern afi_t bgp_node_afi (struct vty *); extern safi_t bgp_node_safi (struct vty *); diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 11e888d7e9..8ecd025397 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -1367,8 +1367,7 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp, api.tag = tag; } - distance = bgp_distance_apply (p, info, bgp); - + distance = bgp_distance_apply (p, info, afi, safi, bgp); if (distance) { SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE); @@ -1554,6 +1553,13 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp, api.tag = tag; } + distance = bgp_distance_apply (p, info, afi, safi, bgp); + if (distance) + { + SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE); + api.distance = distance; + } + if (p->family == AF_INET) { if (bgp_debug_zebra(p)) diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 71c2c84e61..403468a630 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -7123,6 +7123,8 @@ bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi, struct peer_group *group; struct listnode *node, *nnode; + bgp_config_write_distance (vty, bgp, afi, safi, &write); + bgp_config_write_network (vty, bgp, afi, safi, &write); bgp_config_write_redistribute (vty, bgp, afi, safi, &write); @@ -7371,9 +7373,6 @@ bgp_config_write (struct vty *vty) bgp_config_write_peer_global (vty, bgp, peer); } - /* Distance configuration. */ - bgp_config_write_distance (vty, bgp); - /* listen range and limit for dynamic BGP neighbors */ bgp_config_write_listen (vty, bgp); diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index ee105201e8..f6e8598494 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -320,9 +320,9 @@ struct bgp #define RMAP_DEFAULT_ORIGINATE_EVAL_TIMER 5 /* BGP distance configuration. */ - u_char distance_ebgp; - u_char distance_ibgp; - u_char distance_local; + u_char distance_ebgp[AFI_MAX][SAFI_MAX]; + u_char distance_ibgp[AFI_MAX][SAFI_MAX]; + u_char distance_local[AFI_MAX][SAFI_MAX]; /* BGP default local-preference. */ u_int32_t default_local_pref;