Signed-off-by: Dinesh G Dutt <[email protected]>
Signed-off-by: Donald Sharp <[email protected]>
---
bgpd/bgp_route.c | 373 ++++++++++++++++++++++++++++++++++++++++++++++---------
1 file changed, 316 insertions(+), 57 deletions(-)
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 126dc11..e17396d 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -714,11 +714,12 @@ bgp_cluster_filter (struct peer *peer, struct attr *attr)
static int
bgp_input_modifier (struct peer *peer, struct prefix *p, struct attr *attr,
- afi_t afi, safi_t safi)
+ afi_t afi, safi_t safi, const char *rmap_name)
{
struct bgp_filter *filter;
struct bgp_info info;
route_map_result_t ret;
+ struct route_map *rmap = NULL;
filter = &peer->filter[afi][safi];
@@ -726,8 +727,18 @@ bgp_input_modifier (struct peer *peer, struct prefix *p,
struct attr *attr,
if (peer->weight)
(bgp_attr_extra_get (attr))->weight = peer->weight;
+ if (rmap_name)
+ {
+ rmap = route_map_lookup_by_name(rmap_name);
+ }
+ else
+ {
+ if (ROUTE_MAP_IN_NAME(filter))
+ rmap = ROUTE_MAP_IN (filter);
+ }
+
/* Route map apply. */
- if (ROUTE_MAP_IN_NAME (filter))
+ if (rmap)
{
/* Duplicate current value to new strucutre for modification. */
info.peer = peer;
@@ -736,7 +747,56 @@ bgp_input_modifier (struct peer *peer, struct prefix *p,
struct attr *attr,
SET_FLAG (peer->rmap_type, PEER_RMAP_TYPE_IN);
/* Apply BGP route map to the attribute. */
- ret = route_map_apply (ROUTE_MAP_IN (filter), p, RMAP_BGP, &info);
+ ret = route_map_apply (rmap, p, RMAP_BGP, &info);
+
+ peer->rmap_type = 0;
+
+ if (ret == RMAP_DENYMATCH)
+ {
+ /* Free newly generated AS path and community by route-map. */
+ bgp_attr_flush (attr);
+ return RMAP_DENY;
+ }
+ }
+ return RMAP_PERMIT;
+}
+
+static int
+bgp_output_modifier (struct peer *peer, struct prefix *p, struct attr *attr,
+ afi_t afi, safi_t safi, const char *rmap_name)
+{
+ struct bgp_filter *filter;
+ struct bgp_info info;
+ route_map_result_t ret;
+ struct route_map *rmap = NULL;
+
+ filter = &peer->filter[afi][safi];
+
+ /* Apply default weight value. */
+ if (peer->weight)
+ (bgp_attr_extra_get (attr))->weight = peer->weight;
+
+ if (rmap_name)
+ {
+ rmap = route_map_lookup_by_name(rmap_name);
+ }
+ else
+ {
+ if (ROUTE_MAP_OUT_NAME(filter))
+ rmap = ROUTE_MAP_OUT (filter);
+ }
+
+ /* Route map apply. */
+ if (rmap)
+ {
+ /* Duplicate current value to new strucutre for modification. */
+ info.peer = peer;
+ info.attr = attr;
+
+ SET_FLAG (peer->rmap_type, PEER_RMAP_TYPE_OUT);
+
+ /* Apply BGP route map to the attribute. */
+ ret = route_map_apply (rmap, p, RMAP_BGP, &info);
peer->rmap_type = 0;
@@ -2269,7 +2329,7 @@ bgp_update_main (struct peer *peer, struct prefix *p,
struct attr *attr,
* NB: new_attr may now contain newly allocated values from route-map "set"
* commands, so we need bgp_attr_flush in the error paths, until we intern
* the attr (which takes over the memory references) */
- if (bgp_input_modifier (peer, p, &new_attr, afi, safi) == RMAP_DENY)
+ if (bgp_input_modifier (peer, p, &new_attr, afi, safi, NULL) == RMAP_DENY)
{
reason = "route-map;";
bgp_attr_flush (&new_attr);
@@ -10292,19 +10352,22 @@ DEFUN (show_ip_bgp_vpnv4_neighbor_prefix_counts,
return bgp_peer_counts (vty, peer, AFI_IP, SAFI_MPLS_VPN);
}
-
static void
show_adj_route (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi,
- int in)
+ int in, char *delim, const char *rmap_name)
{
struct bgp_table *table;
struct bgp_adj_in *ain;
struct bgp_adj_out *adj;
unsigned long output_count;
+ unsigned long filtered_count;
struct bgp_node *rn;
int header1 = 1;
struct bgp *bgp;
int header2 = 1;
+ struct attr attr;
+ struct attr_extra extra;
+ int ret;
bgp = peer->bgp;
@@ -10313,8 +10376,8 @@ show_adj_route (struct vty *vty, struct peer *peer,
afi_t afi, safi_t safi,
table = bgp->rib[afi][safi];
- output_count = 0;
-
+ output_count = filtered_count = 0;
+
if (! in && CHECK_FLAG (peer->af_sflags[afi][safi],
PEER_STATUS_DEFAULT_ORIGINATE))
{
@@ -10327,6 +10390,7 @@ show_adj_route (struct vty *vty, struct peer *peer,
afi_t afi, safi_t safi,
header1 = 0;
}
+ attr.extra = &extra;
for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
if (in)
{
@@ -10346,9 +10410,16 @@ show_adj_route (struct vty *vty, struct peer *peer,
afi_t afi, safi_t safi,
header2 = 0;
}
if (ain->attr)
- {
- route_vty_out_tmp (vty, &rn->p, ain->attr, safi);
- output_count++;
+ {
+ bgp_attr_dup(&attr, ain->attr);
+ if (bgp_input_modifier(peer, &rn->p, &attr, afi,
+ safi, rmap_name) != RMAP_DENY)
+ {
+ route_vty_out_tmp (vty, &rn->p, &attr, safi);
+ output_count++;
+ }
+ else
+ filtered_count++;
}
}
}
@@ -10370,9 +10441,26 @@ show_adj_route (struct vty *vty, struct peer *peer,
afi_t afi, safi_t safi,
header2 = 0;
}
if (adj->attr)
- {
- route_vty_out_tmp (vty, &rn->p, adj->attr, safi);
- output_count++;
+ {
+ if (!CHECK_FLAG(peer->af_flags[afi][safi],
+ PEER_FLAG_REFLECTOR_CLIENT)
+ || bgp_flag_check(bgp, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY))
+ {
+
+ bgp_attr_dup(&attr, adj->attr);
+ ret = bgp_output_modifier(peer, &rn->p, &attr, afi,
+ safi, rmap_name);
+ }
+ else
+ ret = RMAP_PERMIT;
+
+ if (ret != RMAP_DENY)
+ {
+ route_vty_out_tmp (vty, &rn->p, &attr, safi);
+ output_count++;
+ }
+ else
+ filtered_count++;
}
}
}