#include "filter.h"
#include "command.h"
#include "srv6.h"
+#include "frrstr.h"
#include "bgpd/bgpd.h"
#include "bgpd/bgp_attr.h"
/* Atomic aggregate. */
static int bgp_attr_atomic(struct bgp_attr_parser_args *args)
{
+ struct peer *const peer = args->peer;
struct attr *const attr = args->attr;
const bgp_size_t length = args->length;
args->total);
}
+ if (peer->discard_attrs[args->type])
+ goto atomic_ignore;
+
/* Set atomic aggregate flag. */
attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
return BGP_ATTR_PARSE_PROCEED;
+
+atomic_ignore:
+ stream_forward_getp(peer->curr, length);
+
+ if (bgp_debug_update(peer, NULL, NULL, 1))
+ zlog_debug("%pBP: Ignoring attribute %s", peer,
+ lookup_msg(attr_str, args->type, NULL));
+
+ return BGP_ATTR_PARSE_PROCEED;
}
/* Aggregator attribute */
args->total);
}
+ if (peer->discard_attrs[args->type])
+ goto aggregator_ignore;
+
if (CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV))
aggregator_as = stream_getl(peer->curr);
else
}
return BGP_ATTR_PARSE_PROCEED;
+
+aggregator_ignore:
+ stream_forward_getp(peer->curr, length);
+
+ if (bgp_debug_update(peer, NULL, NULL, 1))
+ zlog_debug("%pBP: Ignoring attribute %s", peer,
+ lookup_msg(attr_str, args->type, NULL));
+
+ return BGP_ATTR_PARSE_PROCEED;
}
/* New Aggregator attribute */
0);
}
+ if (peer->discard_attrs[args->type])
+ goto as4_aggregator_ignore;
+
aggregator_as = stream_getl(peer->curr);
*as4_aggregator_as = aggregator_as;
}
return BGP_ATTR_PARSE_PROCEED;
+
+as4_aggregator_ignore:
+ stream_forward_getp(peer->curr, length);
+
+ if (bgp_debug_update(peer, NULL, NULL, 1))
+ zlog_debug("%pBP: Ignoring attribute %s", peer,
+ lookup_msg(attr_str, args->type, NULL));
+
+ return BGP_ATTR_PARSE_PROCEED;
}
/* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
args->total);
}
+ if (peer->discard_attrs[args->type])
+ goto community_ignore;
+
bgp_attr_set_community(
attr,
community_parse((uint32_t *)stream_pnt(peer->curr), length));
args->total);
return BGP_ATTR_PARSE_PROCEED;
+
+community_ignore:
+ stream_forward_getp(peer->curr, length);
+
+ if (bgp_debug_update(peer, NULL, NULL, 1))
+ zlog_debug("%pBP: Ignoring attribute %s", peer,
+ lookup_msg(attr_str, args->type, NULL));
+
+ return BGP_ATTR_PARSE_PROCEED;
}
/* Originator ID attribute. */
args->total);
}
+ if (peer->discard_attrs[args->type])
+ goto originator_id_ignore;
+
attr->originator_id.s_addr = stream_get_ipv4(peer->curr);
attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID);
return BGP_ATTR_PARSE_PROCEED;
+
+originator_id_ignore:
+ stream_forward_getp(peer->curr, length);
+
+ if (bgp_debug_update(peer, NULL, NULL, 1))
+ zlog_debug("%pBP: Ignoring attribute %s", peer,
+ lookup_msg(attr_str, args->type, NULL));
+
+ return BGP_ATTR_PARSE_PROCEED;
}
/* Cluster list attribute. */
args->total);
}
+ if (peer->discard_attrs[args->type])
+ goto cluster_list_ignore;
+
bgp_attr_set_cluster(
attr, cluster_parse((struct in_addr *)stream_pnt(peer->curr),
length));
attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST);
return BGP_ATTR_PARSE_PROCEED;
+
+cluster_list_ignore:
+ stream_forward_getp(peer->curr, length);
+
+ if (bgp_debug_update(peer, NULL, NULL, 1))
+ zlog_debug("%pBP: Ignoring attribute %s", peer,
+ lookup_msg(attr_str, args->type, NULL));
+
+ return BGP_ATTR_PARSE_PROCEED;
}
/* Multiprotocol reachability information parse. */
args->total);
}
+ if (peer->discard_attrs[args->type])
+ goto large_community_ignore;
+
bgp_attr_set_lcommunity(
attr, lcommunity_parse(stream_pnt(peer->curr), length));
/* XXX: fix ecommunity_parse to use stream API */
args->total);
return BGP_ATTR_PARSE_PROCEED;
+
+large_community_ignore:
+ stream_forward_getp(peer->curr, length);
+
+ if (bgp_debug_update(peer, NULL, NULL, 1))
+ zlog_debug("%pBP: Ignoring attribute %s", peer,
+ lookup_msg(attr_str, args->type, NULL));
+
+ return BGP_ATTR_PARSE_PROCEED;
}
/* Extended Community attribute. */
args->total);
}
+ if (peer->discard_attrs[args->type])
+ goto ipv6_ext_community_ignore;
+
ipv6_ecomm = ecommunity_parse_ipv6(
stream_pnt(peer->curr), length,
CHECK_FLAG(peer->flags,
args->total);
return BGP_ATTR_PARSE_PROCEED;
+
+ipv6_ext_community_ignore:
+ stream_forward_getp(peer->curr, length);
+
+ if (bgp_debug_update(peer, NULL, NULL, 1))
+ zlog_debug("%pBP: Ignoring attribute %s", peer,
+ lookup_msg(attr_str, args->type, NULL));
+
+ return BGP_ATTR_PARSE_PROCEED;
}
/* Parse Tunnel Encap attribute in an UPDATE */
goto aigp_ignore;
}
+ if (peer->discard_attrs[args->type])
+ goto aigp_ignore;
+
if (!bgp_attr_aigp_valid(s, length))
goto aigp_ignore;
aigp_ignore:
stream_forward_getp(peer->curr, length);
+ if (bgp_debug_update(peer, NULL, NULL, 1))
+ zlog_debug("%pBP: Ignoring attribute %s", peer,
+ lookup_msg(attr_str, args->type, NULL));
+
return BGP_ATTR_PARSE_PROCEED;
}
args->total);
}
+ if (peer->discard_attrs[args->type])
+ goto otc_ignore;
+
attr->otc = stream_getl(peer->curr);
if (!attr->otc) {
flog_err(EC_BGP_ATTR_MAL_AS_PATH, "OTC attribute value is 0");
attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_OTC);
return BGP_ATTR_PARSE_PROCEED;
+
+otc_ignore:
+ stream_forward_getp(peer->curr, length);
+
+ if (bgp_debug_update(peer, NULL, NULL, 1))
+ zlog_debug("%pBP: Ignoring attribute %s", peer,
+ lookup_msg(attr_str, args->type, NULL));
+
+ return BGP_ATTR_PARSE_PROCEED;
}
/* BGP unknown attribute treatment. */
/* Forward read pointer of input stream. */
stream_forward_getp(peer->curr, length);
+ if (peer->discard_attrs[type]) {
+ if (bgp_debug_update(peer, NULL, NULL, 1))
+ zlog_debug("%pBP: Ignoring attribute %s", peer,
+ lookup_msg(attr_str, args->type, NULL));
+
+ return BGP_ATTR_PARSE_PROCEED;
+ }
+
/* If any of the mandatory well-known attributes are not recognized,
then the Error Subcode is set to Unrecognized Well-known
Attribute. The Data field contains the unrecognized attribute
len = stream_get_endp(s) - cp - 2;
stream_putw_at(s, cp, len);
}
+
+void bgp_path_attribute_discard_vty(struct vty *vty, struct peer *peer,
+ const char *discard_attrs)
+{
+ int i, num_attributes;
+ char **attributes;
+ afi_t afi;
+ safi_t safi;
+
+ if (discard_attrs) {
+ frrstr_split(discard_attrs, " ", &attributes, &num_attributes);
+
+ for (i = 0; i < BGP_ATTR_MAX; i++)
+ peer->discard_attrs[i] = false;
+
+ for (i = 0; i < num_attributes; i++) {
+ uint8_t attr_num = strtoul(attributes[i], NULL, 10);
+
+ XFREE(MTYPE_TMP, attributes[i]);
+
+ /* Some of the attributes, just can't be ignored. */
+ if (attr_num == BGP_ATTR_ORIGIN ||
+ attr_num == BGP_ATTR_AS_PATH ||
+ attr_num == BGP_ATTR_NEXT_HOP ||
+ attr_num == BGP_ATTR_MULTI_EXIT_DISC ||
+ attr_num == BGP_ATTR_MP_REACH_NLRI ||
+ attr_num == BGP_ATTR_MP_UNREACH_NLRI ||
+ attr_num == BGP_ATTR_EXT_COMMUNITIES) {
+ vty_out(vty,
+ "%% Can't discard path-attribute %s, ignoring.\n",
+ lookup_msg(attr_str, attr_num, NULL));
+ continue;
+ }
+
+ /* Ignore local-pref, originator-id, cluster-list only
+ * for eBGP.
+ */
+ if (peer->sort != BGP_PEER_EBGP &&
+ (attr_num == BGP_ATTR_LOCAL_PREF ||
+ attr_num == BGP_ATTR_ORIGINATOR_ID ||
+ attr_num == BGP_ATTR_CLUSTER_LIST)) {
+ vty_out(vty,
+ "%% Can discard path-attribute %s only for eBGP, ignoring.\n",
+ lookup_msg(attr_str, attr_num, NULL));
+ continue;
+ }
+
+ peer->discard_attrs[attr_num] = true;
+ }
+ XFREE(MTYPE_TMP, attributes);
+
+ /* Configuring path attributes to be discarded will trigger
+ * an inbound Route Refresh to ensure that the routing table
+ * is up to date.
+ */
+ FOREACH_AFI_SAFI (afi, safi)
+ peer_clear_soft(peer, afi, safi, BGP_CLEAR_SOFT_IN);
+ }
+}
return CMD_SUCCESS;
}
+DEFPY(neighbor_path_attribute_discard,
+ neighbor_path_attribute_discard_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor path-attribute discard (1-255)...",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Manipulate path attributes from incoming UPDATE messages\n"
+ "Drop specified attributes from incoming UPDATE messages\n"
+ "Attribute number\n")
+{
+ struct peer *peer;
+ int idx = 0;
+ const char *discard_attrs = NULL;
+
+ peer = peer_and_group_lookup_vty(vty, neighbor);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ argv_find(argv, argc, "(1-255)", &idx);
+ if (idx)
+ discard_attrs = argv_concat(argv, argc, idx);
+
+ bgp_path_attribute_discard_vty(vty, peer, discard_attrs);
+
+ return CMD_SUCCESS;
+}
+
static int set_ecom_list(struct vty *vty, int argc, struct cmd_token **argv,
struct ecommunity **list, bool is_rt6)
{
vty_out(vty, " neighbor %s sender-as-path-loop-detection\n",
addr);
+ /* path-attribute discard */
+ char discard_attrs_str[BUFSIZ] = {0};
+ bool discard_attrs = bgp_path_attribute_discard(
+ peer, discard_attrs_str, sizeof(discard_attrs_str));
+
+ if (discard_attrs)
+ vty_out(vty, " neighbor %s path-attribute discard %s\n", addr,
+ discard_attrs_str);
+
if (!CHECK_FLAG(peer->peer_gr_new_status_flag,
PEER_GRACEFUL_RESTART_NEW_STATE_INHERIT)) {
install_element(BGP_NODE, &neighbor_aspath_loop_detection_cmd);
install_element(BGP_NODE, &no_neighbor_aspath_loop_detection_cmd);
+ /* "neighbor path-attribute discard" commands. */
+ install_element(BGP_NODE, &neighbor_path_attribute_discard_cmd);
+
/* "neighbor passive" commands. */
install_element(BGP_NODE, &neighbor_passive_cmd);
install_element(BGP_NODE, &no_neighbor_passive_cmd);