diff options
| author | Donatas Abraitis <donatas@opensourcerouting.org> | 2022-04-25 10:34:36 +0300 | 
|---|---|---|
| committer | Donatas Abraitis <donatas@opensourcerouting.org> | 2022-04-25 14:05:22 +0300 | 
| commit | 77e3d82167b97a1ff4abe59d6e4f12086a61d9f9 (patch) | |
| tree | 5c68e86eaa6fd6b9734e40928b6bee1390377299 /bgpd | |
| parent | c27892b24d21762f3cd4276fa2cca75c958f9b15 (diff) | |
bgpd: Add `set as-path replace <any|ASN>` cmd for route-maps
```
route-map tstas permit 10
 set as-path replace 1
exit
```
Before:
```
donatas-laptop(config-router-af)# do show ip bgp 10.10.10.10/32
BGP routing table entry for 10.10.10.10/32, version 13
Paths: (1 available, best #1, table default)
  Advertised to non peer-group peers:
  192.168.10.65
  65000 1 2 3 123
    192.168.10.65 from 192.168.10.65 (10.10.10.11)
      Origin IGP, metric 0, valid, external, best (First path received)
      Last update: Mon Apr 25 10:39:50 2022
```
After:
```
donatas-laptop(config-router-af)# do show ip bgp 10.10.10.10/32
BGP routing table entry for 10.10.10.10/32, version 15
Paths: (1 available, best #1, table default)
  Advertised to non peer-group peers:
  192.168.10.65
  65000 65010 2 3 123
    192.168.10.65 from 192.168.10.65 (10.10.10.11)
      Origin IGP, metric 0, valid, external, best (First path received)
      Last update: Mon Apr 25 10:40:16 2022
```
Signed-off-by: Donatas Abraitis <donatas@opensourcerouting.org>
Diffstat (limited to 'bgpd')
| -rw-r--r-- | bgpd/bgp_aspath.c | 22 | ||||
| -rw-r--r-- | bgpd/bgp_aspath.h | 2 | ||||
| -rw-r--r-- | bgpd/bgp_routemap.c | 91 | ||||
| -rw-r--r-- | bgpd/bgp_routemap_nb.c | 7 | ||||
| -rw-r--r-- | bgpd/bgp_routemap_nb.h | 4 | ||||
| -rw-r--r-- | bgpd/bgp_routemap_nb_config.c | 52 | 
6 files changed, 178 insertions, 0 deletions
diff --git a/bgpd/bgp_aspath.c b/bgpd/bgp_aspath.c index fd644ebf0a..880e15fadb 100644 --- a/bgpd/bgp_aspath.c +++ b/bgpd/bgp_aspath.c @@ -1258,6 +1258,28 @@ struct aspath *aspath_replace_specific_asn(struct aspath *aspath,  	return new;  } +/* Replace all ASNs with our own ASN */ +struct aspath *aspath_replace_all_asn(struct aspath *aspath, as_t our_asn) +{ +	struct aspath *new; +	struct assegment *seg; + +	new = aspath_dup(aspath); +	seg = new->segments; + +	while (seg) { +		int i; + +		for (i = 0; i < seg->length; i++) +			seg->as[i] = our_asn; + +		seg = seg->next; +	} + +	aspath_str_update(new, false); +	return new; +} +  /* Replace all private ASNs with our own ASN */  struct aspath *aspath_replace_private_asns(struct aspath *aspath, as_t asn,  					   as_t peer_asn) diff --git a/bgpd/bgp_aspath.h b/bgpd/bgp_aspath.h index 4b16818167..912db7b254 100644 --- a/bgpd/bgp_aspath.h +++ b/bgpd/bgp_aspath.h @@ -112,6 +112,8 @@ extern bool aspath_single_asn_check(struct aspath *, as_t asn);  extern struct aspath *aspath_replace_specific_asn(struct aspath *aspath,  						  as_t target_asn,  						  as_t our_asn); +extern struct aspath *aspath_replace_all_asn(struct aspath *aspath, +					     as_t our_asn);  extern struct aspath *aspath_replace_private_asns(struct aspath *aspath,  						  as_t asn, as_t peer_asn);  extern struct aspath *aspath_remove_private_asns(struct aspath *aspath, diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index 6c303a9e5f..20ee2e4d49 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -2174,6 +2174,57 @@ static const struct route_map_rule_cmd route_set_aspath_exclude_cmd = {  	route_aspath_free,  }; +/* `set as-path replace AS-PATH` */ +static void *route_aspath_replace_compile(const char *arg) +{ +	return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); +} + +static void route_aspath_replace_free(void *rule) +{ +	XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); +} + +static enum route_map_cmd_result_t +route_set_aspath_replace(void *rule, const struct prefix *dummy, void *object) +{ +	struct aspath *aspath_new; +	const char *replace = rule; +	struct bgp_path_info *path = object; +	as_t own_asn = path->peer->change_local_as ? path->peer->change_local_as +						   : path->peer->local_as; + +	if (path->peer->sort != BGP_PEER_EBGP) { +		zlog_warn( +			"`set as-path replace` is supported only for EBGP peers"); +		return RMAP_NOOP; +	} + +	if (path->attr->aspath->refcnt) +		aspath_new = aspath_dup(path->attr->aspath); +	else +		aspath_new = path->attr->aspath; + +	if (strmatch(replace, "any")) { +		path->attr->aspath = +			aspath_replace_all_asn(aspath_new, own_asn); +	} else { +		as_t replace_asn = strtoul(replace, NULL, 10); + +		path->attr->aspath = aspath_replace_specific_asn( +			aspath_new, replace_asn, own_asn); +	} + +	return RMAP_OKAY; +} + +static const struct route_map_rule_cmd route_set_aspath_replace_cmd = { +	"as-path replace", +	route_set_aspath_replace, +	route_aspath_replace_compile, +	route_aspath_replace_free, +}; +  /* `set community COMMUNITY' */  struct rmap_com_set {  	struct community *com; @@ -5389,6 +5440,43 @@ DEFUN_YANG (set_aspath_prepend_lastas,  	return nb_cli_apply_changes(vty, NULL);  } +DEFPY_YANG (set_aspath_replace_asn, +	    set_aspath_replace_asn_cmd, +	    "set as-path replace <any|(1-4294967295)>$replace", +	    SET_STR +	    "Transform BGP AS_PATH attribute\n" +	    "Replace AS number to local AS number\n" +	    "Replace any AS number to local AS number\n" +	    "Replace a specific AS number to local AS number\n") +{ +	const char *xpath = +		"./set-action[action='frr-bgp-route-map:as-path-replace']"; +	char xpath_value[XPATH_MAXLEN]; + +	nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); +	snprintf(xpath_value, sizeof(xpath_value), +		 "%s/rmap-set-action/frr-bgp-route-map:replace-as-path", xpath); +	nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, replace); +	return nb_cli_apply_changes(vty, NULL); +} + +DEFPY_YANG (no_set_aspath_replace_asn, +	    no_set_aspath_replace_asn_cmd, +	    "no set as-path replace [<any|(1-4294967295)>]", +	    NO_STR +	    SET_STR +	    "Transform BGP AS_PATH attribute\n" +	    "Replace AS number to local AS number\n" +	    "Replace any AS number to local AS number\n" +	    "Replace a specific AS number to local AS number\n") +{ +	const char *xpath = +		"./set-action[action='frr-bgp-route-map:as-path-replace']"; + +	nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); +	return nb_cli_apply_changes(vty, NULL); +} +  DEFUN_YANG (no_set_aspath_prepend,  	    no_set_aspath_prepend_cmd,  	    "no set as-path prepend [(1-4294967295)]", @@ -6727,6 +6815,7 @@ void bgp_route_map_init(void)  	route_map_install_set(&route_set_distance_cmd);  	route_map_install_set(&route_set_aspath_prepend_cmd);  	route_map_install_set(&route_set_aspath_exclude_cmd); +	route_map_install_set(&route_set_aspath_replace_cmd);  	route_map_install_set(&route_set_origin_cmd);  	route_map_install_set(&route_set_atomic_aggregate_cmd);  	route_map_install_set(&route_set_aggregator_as_cmd); @@ -6800,10 +6889,12 @@ void bgp_route_map_init(void)  	install_element(RMAP_NODE, &set_aspath_prepend_asn_cmd);  	install_element(RMAP_NODE, &set_aspath_prepend_lastas_cmd);  	install_element(RMAP_NODE, &set_aspath_exclude_cmd); +	install_element(RMAP_NODE, &set_aspath_replace_asn_cmd);  	install_element(RMAP_NODE, &no_set_aspath_prepend_cmd);  	install_element(RMAP_NODE, &no_set_aspath_prepend_lastas_cmd);  	install_element(RMAP_NODE, &no_set_aspath_exclude_cmd);  	install_element(RMAP_NODE, &no_set_aspath_exclude_all_cmd); +	install_element(RMAP_NODE, &no_set_aspath_replace_asn_cmd);  	install_element(RMAP_NODE, &set_origin_cmd);  	install_element(RMAP_NODE, &no_set_origin_cmd);  	install_element(RMAP_NODE, &set_atomic_aggregate_cmd); diff --git a/bgpd/bgp_routemap_nb.c b/bgpd/bgp_routemap_nb.c index caf1553ec1..585596e1aa 100644 --- a/bgpd/bgp_routemap_nb.c +++ b/bgpd/bgp_routemap_nb.c @@ -297,6 +297,13 @@ const struct frr_yang_module_info frr_bgp_route_map_info = {  			}  		},  		{ +			.xpath = "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/frr-bgp-route-map:replace-as-path", +			.cbs = { +				.modify = lib_route_map_entry_set_action_rmap_set_action_replace_as_path_modify, +				.destroy = lib_route_map_entry_set_action_rmap_set_action_replace_as_path_destroy, +			} +		}, +		{  			.xpath = "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/frr-bgp-route-map:community-none",  			.cbs = {  				.modify = lib_route_map_entry_set_action_rmap_set_action_community_none_modify, diff --git a/bgpd/bgp_routemap_nb.h b/bgpd/bgp_routemap_nb.h index e0b3a6926f..a01adf7d5d 100644 --- a/bgpd/bgp_routemap_nb.h +++ b/bgpd/bgp_routemap_nb.h @@ -108,6 +108,10 @@ int lib_route_map_entry_set_action_rmap_set_action_last_as_modify(struct nb_cb_m  int lib_route_map_entry_set_action_rmap_set_action_last_as_destroy(struct nb_cb_destroy_args *args);  int lib_route_map_entry_set_action_rmap_set_action_exclude_as_path_modify(struct nb_cb_modify_args *args);  int lib_route_map_entry_set_action_rmap_set_action_exclude_as_path_destroy(struct nb_cb_destroy_args *args); +int lib_route_map_entry_set_action_rmap_set_action_replace_as_path_modify( +	struct nb_cb_modify_args *args); +int lib_route_map_entry_set_action_rmap_set_action_replace_as_path_destroy( +	struct nb_cb_destroy_args *args);  int lib_route_map_entry_set_action_rmap_set_action_community_none_modify(struct nb_cb_modify_args *args);  int lib_route_map_entry_set_action_rmap_set_action_community_none_destroy(struct nb_cb_destroy_args *args);  int lib_route_map_entry_set_action_rmap_set_action_community_string_modify(struct nb_cb_modify_args *args); diff --git a/bgpd/bgp_routemap_nb_config.c b/bgpd/bgp_routemap_nb_config.c index 773538ee41..b87877b1e0 100644 --- a/bgpd/bgp_routemap_nb_config.c +++ b/bgpd/bgp_routemap_nb_config.c @@ -2209,6 +2209,58 @@ lib_route_map_entry_set_action_rmap_set_action_exclude_as_path_destroy(  /*   * XPath: + * /frr-route-map:lib/route-map/entry/set-action/rmap-set-action/frr-bgp-route-map:replace-as-path + */ +int lib_route_map_entry_set_action_rmap_set_action_replace_as_path_modify( +	struct nb_cb_modify_args *args) +{ +	struct routemap_hook_context *rhc; +	const char *type; +	int rv; + +	switch (args->event) { +	case NB_EV_VALIDATE: +	case NB_EV_PREPARE: +	case NB_EV_ABORT: +		break; +	case NB_EV_APPLY: +		/* Add configuration. */ +		rhc = nb_running_get_entry(args->dnode, NULL, true); +		type = yang_dnode_get_string(args->dnode, NULL); + +		/* Set destroy information. */ +		rhc->rhc_shook = generic_set_delete; +		rhc->rhc_rule = "as-path replace"; +		rhc->rhc_event = RMAP_EVENT_SET_DELETED; + +		rv = generic_set_add(rhc->rhc_rmi, "as-path replace", type, +				     args->errmsg, args->errmsg_len); +		if (rv != CMD_SUCCESS) { +			rhc->rhc_shook = NULL; +			return NB_ERR_INCONSISTENCY; +		} +	} + +	return NB_OK; +} + +int lib_route_map_entry_set_action_rmap_set_action_replace_as_path_destroy( +	struct nb_cb_destroy_args *args) +{ +	switch (args->event) { +	case NB_EV_VALIDATE: +	case NB_EV_PREPARE: +	case NB_EV_ABORT: +		break; +	case NB_EV_APPLY: +		return lib_route_map_entry_set_destroy(args); +	} + +	return NB_OK; +} + +/* + * XPath:   * /frr-route-map:lib/route-map/entry/set-action/rmap-set-action/frr-bgp-route-map:community-none   */  int lib_route_map_entry_set_action_rmap_set_action_community_none_modify(  | 
