From 316e074deb5e8f77375609545e89bf68dfd0d8fe Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 19 May 2015 18:03:49 -0700 Subject: [PATCH] bgpd: Add route-map support for set ip next-hop unchanged In the data center, where load balancers are announced as VIPs, and eBGP is used as the routing protocol, this feature is required to ensure that VIP announcements can be made from anywhere the operator sees fit. Signed-off-by: Dinesh G Dutt Signed-off-by: Vivek Venkatraman --- bgpd/bgp_attr.h | 1 + bgpd/bgp_route.c | 4 ++++ bgpd/bgp_routemap.c | 24 +++++++++++++++++++++++- bgpd/bgp_updgrp.h | 1 + bgpd/bgp_updgrp_packet.c | 13 +++++++++++-- 5 files changed, 40 insertions(+), 3 deletions(-) diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h index 57eca3abbb..67d92b2bdd 100644 --- a/bgpd/bgp_attr.h +++ b/bgpd/bgp_attr.h @@ -126,6 +126,7 @@ struct attr #define BATTR_RMAP_NEXTHOP_CHANGED (1 << 0) #define BATTR_RMAP_NEXTHOP_PEER_ADDRESS (1 << 1) #define BATTR_REFLECTED (1 << 2) +#define BATTR_RMAP_NEXTHOP_UNCHANGED (1 << 3) /* Router Reflector related structure. */ struct cluster_list diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index f463c42747..4ea5ad841f 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -1493,6 +1493,8 @@ subgroup_announce_check (struct bgp_info *ri, struct update_subgroup *subgrp, info.peer = peer; info.attr = attr; + /* don't confuse inbound and outbound setting */ + RESET_FLAG(attr->rmap_change_flags); /* * The route reflector is not allowed to modify the attributes @@ -1530,6 +1532,8 @@ subgroup_announce_check (struct bgp_info *ri, struct update_subgroup *subgrp, * Also see earlier comments in this function. */ if (!(CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_NEXTHOP_CHANGED) || + CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_NEXTHOP_UNCHANGED) || + CHECK_FLAG(riattr->rmap_change_flags, BATTR_RMAP_NEXTHOP_UNCHANGED) || transparent || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED))) { diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index c2dba97a70..f133a57a19 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -1079,6 +1079,7 @@ struct rmap_ip_nexthop_set { struct in_addr *address; int peer_address; + int unchanged; }; static route_map_result_t @@ -1094,7 +1095,12 @@ route_set_ip_nexthop (void *rule, struct prefix *prefix, bgp_info = object; peer = bgp_info->peer; - if (rins->peer_address) + if (rins->unchanged) + { + SET_FLAG(bgp_info->attr->rmap_change_flags, + BATTR_RMAP_NEXTHOP_UNCHANGED); + } + else if (rins->peer_address) { if ((CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_IN) || CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_IMPORT)) @@ -1138,10 +1144,13 @@ route_set_ip_nexthop_compile (const char *arg) struct rmap_ip_nexthop_set *rins; struct in_addr *address = NULL; int peer_address = 0; + int unchanged = 0; int ret; if (strcmp (arg, "peer-address") == 0) peer_address = 1; + else if (strcmp (arg, "unchanged") == 0) + unchanged = 1; else { address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in_addr)); @@ -1158,6 +1167,7 @@ route_set_ip_nexthop_compile (const char *arg) rins->address = address; rins->peer_address = peer_address; + rins->unchanged = unchanged; return rins; } @@ -3645,6 +3655,17 @@ DEFUN (set_ip_nexthop_peer, return bgp_route_set_add (vty, vty->index, "ip next-hop", "peer-address"); } +DEFUN (set_ip_nexthop_unchanged, + set_ip_nexthop_unchanged_cmd, + "set ip next-hop unchanged", + SET_STR + IP_STR + "Next hop address\n" + "Don't modify existing Next hop address\n") +{ + return bgp_route_set_add (vty, vty->index, "ip next-hop", "unchanged"); +} + DEFUN_DEPRECATED (no_set_ip_nexthop_peer, no_set_ip_nexthop_peer_cmd, "no set ip next-hop peer-address", @@ -4693,6 +4714,7 @@ bgp_route_map_init (void) install_element (RMAP_NODE, &set_ip_nexthop_cmd); install_element (RMAP_NODE, &set_ip_nexthop_peer_cmd); + install_element (RMAP_NODE, &set_ip_nexthop_unchanged_cmd); install_element (RMAP_NODE, &no_set_ip_nexthop_cmd); install_element (RMAP_NODE, &no_set_ip_nexthop_val_cmd); install_element (RMAP_NODE, &set_local_pref_cmd); diff --git a/bgpd/bgp_updgrp.h b/bgpd/bgp_updgrp.h index aa2ef50362..465a1142a0 100644 --- a/bgpd/bgp_updgrp.h +++ b/bgpd/bgp_updgrp.h @@ -70,6 +70,7 @@ typedef struct #define BPACKET_ATTRVEC_FLAGS_RMAP_CHANGED (1 << 1) #define BPACKET_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS (1 << 2) #define BPACKET_ATTRVEC_FLAGS_REFLECTED (1 << 3) +#define BPACKET_ATTRVEC_FLAGS_RMAP_NH_UNCHANGED (1 << 4) typedef struct bpacket_attr_vec_arr { diff --git a/bgpd/bgp_updgrp_packet.c b/bgpd/bgp_updgrp_packet.c index 8ca4e79319..422df42ebd 100644 --- a/bgpd/bgp_updgrp_packet.c +++ b/bgpd/bgp_updgrp_packet.c @@ -439,7 +439,9 @@ bpacket_reformat_for_peer (struct bpacket *pkt, struct peer_af *paf) CHECK_FLAG(vec->flags, BPACKET_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS))) stream_put_in_addr_at (s, vec->offset + 1, &paf->peer->nexthop.v4); - else if (paf->peer->sort == BGP_PEER_EBGP && + else if (!CHECK_FLAG(vec->flags, + BPACKET_ATTRVEC_FLAGS_RMAP_NH_UNCHANGED) && + paf->peer->sort == BGP_PEER_EBGP && !peer_af_flag_check (paf->peer, paf->afi, paf->safi, PEER_FLAG_NEXTHOP_UNCHANGED)) { @@ -515,7 +517,9 @@ bpacket_reformat_for_peer (struct bpacket *pkt, struct peer_af *paf) BPACKET_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS))) stream_put_in6_addr_at (s, vec->offset + 1, &paf->peer->nexthop.v6_global); - else if (paf->peer->sort == BGP_PEER_EBGP && + else if (!CHECK_FLAG(vec->flags, + BPACKET_ATTRVEC_FLAGS_RMAP_NH_UNCHANGED) && + paf->peer->sort == BGP_PEER_EBGP && !peer_af_flag_check (paf->peer, paf->afi, paf->safi, PEER_FLAG_NEXTHOP_UNCHANGED)) { @@ -1097,6 +1101,11 @@ bpacket_vec_arr_inherit_attr_flags (struct bpacket_attr_vec_arr *vecarr, if (CHECK_FLAG (attr->rmap_change_flags, BATTR_REFLECTED)) SET_FLAG (vecarr->entries[BGP_ATTR_VEC_NH].flags, BPACKET_ATTRVEC_FLAGS_REFLECTED); + + if (CHECK_FLAG (attr->rmap_change_flags, + BATTR_RMAP_NEXTHOP_UNCHANGED)) + SET_FLAG (vecarr->entries[BGP_ATTR_VEC_NH].flags, + BPACKET_ATTRVEC_FLAGS_RMAP_NH_UNCHANGED); } /* Reset the Attributes vector array. The vector array is used to override -- 2.39.5