Skip to content

Commit 841f7a5

Browse files
author
Denis Ovsienko
committed
+ [bgpd] Added new route-map set statement: "as-path ignore"
1 parent 693b67b commit 841f7a5

File tree

6 files changed

+212
-10
lines changed

6 files changed

+212
-10
lines changed

NEWS

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
- [bgpd] 4-byte AS support added
44
- [bgpd] MRT format changes to version 2. Those relying on
55
bgpd MRT table dumps may need to update their tools.
6+
- [bgpd] Added new route-map set statement: "as-path ignore"
67

78
* Changes in Quagga 0.99.2
89

bgpd/ChangeLog

+11
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
1+
2008-04-10 Denis Ovsienko
2+
* bgp_aspath.[ch]: (aspath_filter_exclude) New function allows
3+
filtering out arbitrary ASns from AS_PATH attribute.
4+
* bgp_aspath.[ch]: (aspath_print_vty) Accept suffix to let calling
5+
functions signal, if they want the separator or not.
6+
* bgp_route.c: (route_vty_out, route_vty_out_tmp, damp_route_vty_out,
7+
flap_route_vty_out, route_vty_out_detail) Fix aspath_print_vty()
8+
calls to have AS_PATH output nicely.
9+
* bgp_routemap.c: Introduce "set as-path exclude" route-map command
10+
to employ new filtering functionality.
11+
112
2008-03-13 Paul Jakma <[email protected]>
213

314
* (various) Remove 0 entries from struct message's, unneeded due to

bgpd/bgp_aspath.c

+81-1
Original file line numberDiff line numberDiff line change
@@ -1225,6 +1225,81 @@ aspath_prepend (struct aspath *as1, struct aspath *as2)
12251225
/* Not reached */
12261226
}
12271227

1228+
/* Iterate over AS_PATH segments and wipe all occurences of the
1229+
* listed AS numbers. Hence some segments may lose some or even
1230+
* all data on the way, the operation is implemented as a smarter
1231+
* version of aspath_dup(), which allocates memory to hold the new
1232+
* data, not the original. The new AS path is returned.
1233+
*/
1234+
struct aspath *
1235+
aspath_filter_exclude (struct aspath * source, struct aspath * exclude_list)
1236+
{
1237+
struct assegment * srcseg, * exclseg, * lastseg;
1238+
struct aspath * newpath;
1239+
1240+
newpath = aspath_new();
1241+
lastseg = NULL;
1242+
1243+
for (srcseg = source->segments; srcseg; srcseg = srcseg->next)
1244+
{
1245+
unsigned i, y, newlen = 0, done = 0, skip_as;
1246+
struct assegment * newseg;
1247+
1248+
/* Find out, how much ASns are we going to pick from this segment.
1249+
* We can't perform filtering right inline, because the size of
1250+
* the new segment isn't known at the moment yet.
1251+
*/
1252+
for (i = 0; i < srcseg->length; i++)
1253+
{
1254+
skip_as = 0;
1255+
for (exclseg = exclude_list->segments; exclseg && !skip_as; exclseg = exclseg->next)
1256+
for (y = 0; y < exclseg->length; y++)
1257+
if (srcseg->as[i] == exclseg->as[y])
1258+
{
1259+
skip_as = 1;
1260+
// There's no sense in testing the rest of exclusion list, bail out.
1261+
break;
1262+
}
1263+
if (!skip_as)
1264+
newlen++;
1265+
}
1266+
/* newlen is now the number of ASns to copy */
1267+
if (!newlen)
1268+
continue;
1269+
1270+
/* Actual copying. Allocate memory and iterate once more, performing filtering. */
1271+
newseg = assegment_new (srcseg->type, newlen);
1272+
for (i = 0; i < srcseg->length; i++)
1273+
{
1274+
skip_as = 0;
1275+
for (exclseg = exclude_list->segments; exclseg && !skip_as; exclseg = exclseg->next)
1276+
for (y = 0; y < exclseg->length; y++)
1277+
if (srcseg->as[i] == exclseg->as[y])
1278+
{
1279+
skip_as = 1;
1280+
break;
1281+
}
1282+
if (skip_as)
1283+
continue;
1284+
newseg->as[done++] = srcseg->as[i];
1285+
}
1286+
/* At his point newlen must be equal to done, and both must be positive. Append
1287+
* the filtered segment to the gross result. */
1288+
if (!lastseg)
1289+
newpath->segments = newseg;
1290+
else
1291+
lastseg->next = newseg;
1292+
lastseg = newseg;
1293+
}
1294+
aspath_str_update (newpath);
1295+
/* We are happy returning even an empty AS_PATH, because the administrator
1296+
* might expect this very behaviour. There's a mean to avoid this, if necessary,
1297+
* by having a match rule against certain AS_PATH regexps in the route-map index.
1298+
*/
1299+
aspath_free (source);
1300+
return newpath;
1301+
}
1302+
12281303
/* Add specified AS to the leftmost of aspath. */
12291304
static struct aspath *
12301305
aspath_add_one_as (struct aspath *aspath, as_t asno, u_char type)
@@ -1741,11 +1816,16 @@ aspath_print (struct aspath *as)
17411816
}
17421817

17431818
/* Printing functions */
1819+
/* Feed the AS_PATH to the vty; the suffix string follows it only in case
1820+
* AS_PATH wasn't empty.
1821+
*/
17441822
void
1745-
aspath_print_vty (struct vty *vty, const char *format, struct aspath *as)
1823+
aspath_print_vty (struct vty *vty, const char *format, struct aspath *as, const char * suffix)
17461824
{
17471825
assert (format);
17481826
vty_out (vty, format, as->str);
1827+
if (strlen (as->str) && strlen (suffix))
1828+
vty_out (vty, "%s", suffix);
17491829
}
17501830

17511831
static void

bgpd/bgp_aspath.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ extern struct aspath *aspath_parse (struct stream *, size_t, int);
6969
extern struct aspath *aspath_dup (struct aspath *);
7070
extern struct aspath *aspath_aggregate (struct aspath *, struct aspath *);
7171
extern struct aspath *aspath_prepend (struct aspath *, struct aspath *);
72+
extern struct aspath *aspath_filter_exclude (struct aspath *, struct aspath *);
7273
extern struct aspath *aspath_add_seq (struct aspath *, as_t);
7374
extern struct aspath *aspath_add_confed_seq (struct aspath *, as_t);
7475
extern int aspath_cmp_left (struct aspath *, struct aspath *);
@@ -81,7 +82,7 @@ extern void aspath_free (struct aspath *);
8182
extern struct aspath *aspath_intern (struct aspath *);
8283
extern void aspath_unintern (struct aspath *);
8384
extern const char *aspath_print (struct aspath *);
84-
extern void aspath_print_vty (struct vty *, const char *, struct aspath *);
85+
extern void aspath_print_vty (struct vty *, const char *, struct aspath *, const char *);
8586
extern void aspath_print_all_vty (struct vty *);
8687
extern unsigned int aspath_key_make (void *);
8788
extern int aspath_loop_check (struct aspath *, as_t);

bgpd/bgp_route.c

+5-5
Original file line numberDiff line numberDiff line change
@@ -5694,7 +5694,7 @@ route_vty_out (struct vty *vty, struct prefix *p,
56945694

56955695
/* Print aspath */
56965696
if (attr->aspath)
5697-
aspath_print_vty (vty, "%s ", attr->aspath);
5697+
aspath_print_vty (vty, "%s", attr->aspath, " ");
56985698

56995699
/* Print origin */
57005700
vty_out (vty, "%s", bgp_origin_str[attr->origin]);
@@ -5759,7 +5759,7 @@ route_vty_out_tmp (struct vty *vty, struct prefix *p,
57595759

57605760
/* Print aspath */
57615761
if (attr->aspath)
5762-
aspath_print_vty (vty, "%s ", attr->aspath);
5762+
aspath_print_vty (vty, "%s", attr->aspath, " ");
57635763

57645764
/* Print origin */
57655765
vty_out (vty, "%s", bgp_origin_str[attr->origin]);
@@ -5859,7 +5859,7 @@ damp_route_vty_out (struct vty *vty, struct prefix *p,
58595859
{
58605860
/* Print aspath */
58615861
if (attr->aspath)
5862-
aspath_print_vty (vty, "%s ", attr->aspath);
5862+
aspath_print_vty (vty, "%s", attr->aspath, " ");
58635863

58645864
/* Print origin */
58655865
vty_out (vty, "%s", bgp_origin_str[attr->origin]);
@@ -5922,7 +5922,7 @@ flap_route_vty_out (struct vty *vty, struct prefix *p,
59225922
{
59235923
/* Print aspath */
59245924
if (attr->aspath)
5925-
aspath_print_vty (vty, "%s ", attr->aspath);
5925+
aspath_print_vty (vty, "%s", attr->aspath, " ");
59265926

59275927
/* Print origin */
59285928
vty_out (vty, "%s", bgp_origin_str[attr->origin]);
@@ -5950,7 +5950,7 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p,
59505950
if (aspath_count_hops (attr->aspath) == 0)
59515951
vty_out (vty, "Local");
59525952
else
5953-
aspath_print_vty (vty, "%s", attr->aspath);
5953+
aspath_print_vty (vty, "%s", attr->aspath, "");
59545954
}
59555955

59565956
if (CHECK_FLAG (binfo->flags, BGP_INFO_REMOVED))

bgpd/bgp_routemap.c

+112-3
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ o Local extention
9494
set ipv6 next-hop global: Done
9595
set ipv6 next-hop local : Done
9696
set pathlimit ttl : Done
97+
set as-path exclude : Done
9798
match pathlimit as : Done
9899
99100
*/
@@ -1274,6 +1275,64 @@ struct route_map_rule_cmd route_set_aspath_prepend_cmd =
12741275
route_set_aspath_prepend_free,
12751276
};
12761277

1278+
/* `set as-path exclude ASn' */
1279+
1280+
/* For ASN exclude mechanism.
1281+
* Iterate over ASns requested and filter them from the given AS_PATH one by one.
1282+
* Make a deep copy of existing AS_PATH, but for the first ASn only.
1283+
*/
1284+
static route_map_result_t
1285+
route_set_aspath_exclude (void *rule, struct prefix *dummy, route_map_object_t type, void *object)
1286+
{
1287+
struct aspath * new_path, * exclude_path;
1288+
struct bgp_info *binfo;
1289+
1290+
if (type == RMAP_BGP)
1291+
{
1292+
exclude_path = rule;
1293+
binfo = object;
1294+
if (binfo->attr->aspath->refcnt)
1295+
new_path = aspath_dup (binfo->attr->aspath);
1296+
else
1297+
new_path = binfo->attr->aspath;
1298+
binfo->attr->aspath = aspath_filter_exclude (new_path, exclude_path);
1299+
}
1300+
return RMAP_OKAY;
1301+
}
1302+
1303+
/* FIXME: consider using route_set_aspath_prepend_compile() and
1304+
* route_set_aspath_prepend_free(), which two below function are
1305+
* exact clones of.
1306+
*/
1307+
1308+
/* Compile function for as-path exclude. */
1309+
static void *
1310+
route_set_aspath_exclude_compile (const char *arg)
1311+
{
1312+
struct aspath *aspath;
1313+
1314+
aspath = aspath_str2aspath (arg);
1315+
if (! aspath)
1316+
return NULL;
1317+
return aspath;
1318+
}
1319+
1320+
static void
1321+
route_set_aspath_exclude_free (void *rule)
1322+
{
1323+
struct aspath *aspath = rule;
1324+
aspath_free (aspath);
1325+
}
1326+
1327+
/* Set ASn exlude rule structure. */
1328+
struct route_map_rule_cmd route_set_aspath_exclude_cmd =
1329+
{
1330+
"as-path exclude",
1331+
route_set_aspath_exclude,
1332+
route_set_aspath_exclude_compile,
1333+
route_set_aspath_exclude_free,
1334+
};
1335+
12771336
/* `set community COMMUNITY' */
12781337
struct rmap_com_set
12791338
{
@@ -2996,7 +3055,7 @@ DEFUN (set_aspath_prepend,
29963055
set_aspath_prepend_cmd,
29973056
"set as-path prepend .<1-65535>",
29983057
SET_STR
2999-
"Prepend string for a BGP AS-path attribute\n"
3058+
"Transform BGP AS_PATH attribute\n"
30003059
"Prepend to the as-path\n"
30013060
"AS number\n")
30023061
{
@@ -3015,7 +3074,7 @@ DEFUN (no_set_aspath_prepend,
30153074
"no set as-path prepend",
30163075
NO_STR
30173076
SET_STR
3018-
"Prepend string for a BGP AS-path attribute\n"
3077+
"Transform BGP AS_PATH attribute\n"
30193078
"Prepend to the as-path\n")
30203079
{
30213080
int ret;
@@ -3035,10 +3094,56 @@ ALIAS (no_set_aspath_prepend,
30353094
"no set as-path prepend .<1-65535>",
30363095
NO_STR
30373096
SET_STR
3038-
"Prepend string for a BGP AS-path attribute\n"
3097+
"Transform BGP AS_PATH attribute\n"
30393098
"Prepend to the as-path\n"
30403099
"AS number\n")
30413100

3101+
DEFUN (set_aspath_exclude,
3102+
set_aspath_exclude_cmd,
3103+
"set as-path exclude .<1-65535>",
3104+
SET_STR
3105+
"Transform BGP AS-path attribute\n"
3106+
"Exclude from the as-path\n"
3107+
"AS number\n")
3108+
{
3109+
int ret;
3110+
char *str;
3111+
3112+
str = argv_concat (argv, argc, 0);
3113+
ret = bgp_route_set_add (vty, vty->index, "as-path exclude", str);
3114+
XFREE (MTYPE_TMP, str);
3115+
return ret;
3116+
}
3117+
3118+
DEFUN (no_set_aspath_exclude,
3119+
no_set_aspath_exclude_cmd,
3120+
"no set as-path exclude",
3121+
NO_STR
3122+
SET_STR
3123+
"Transform BGP AS_PATH attribute\n"
3124+
"Exclude from the as-path\n")
3125+
{
3126+
int ret;
3127+
char *str;
3128+
3129+
if (argc == 0)
3130+
return bgp_route_set_delete (vty, vty->index, "as-path exclude", NULL);
3131+
3132+
str = argv_concat (argv, argc, 0);
3133+
ret = bgp_route_set_delete (vty, vty->index, "as-path exclude", str);
3134+
XFREE (MTYPE_TMP, str);
3135+
return ret;
3136+
}
3137+
3138+
ALIAS (no_set_aspath_exclude,
3139+
no_set_aspath_exclude_val_cmd,
3140+
"no set as-path exclude .<1-65535>",
3141+
NO_STR
3142+
SET_STR
3143+
"Transform BGP AS_PATH attribute\n"
3144+
"Exclude from the as-path\n"
3145+
"AS number\n")
3146+
30423147
DEFUN (set_community,
30433148
set_community_cmd,
30443149
"set community .AA:NN",
@@ -3731,6 +3836,7 @@ bgp_route_map_init (void)
37313836
route_map_install_set (&route_set_weight_cmd);
37323837
route_map_install_set (&route_set_metric_cmd);
37333838
route_map_install_set (&route_set_aspath_prepend_cmd);
3839+
route_map_install_set (&route_set_aspath_exclude_cmd);
37343840
route_map_install_set (&route_set_origin_cmd);
37353841
route_map_install_set (&route_set_atomic_aggregate_cmd);
37363842
route_map_install_set (&route_set_aggregator_as_cmd);
@@ -3799,8 +3905,11 @@ bgp_route_map_init (void)
37993905
install_element (RMAP_NODE, &no_set_metric_cmd);
38003906
install_element (RMAP_NODE, &no_set_metric_val_cmd);
38013907
install_element (RMAP_NODE, &set_aspath_prepend_cmd);
3908+
install_element (RMAP_NODE, &set_aspath_exclude_cmd);
38023909
install_element (RMAP_NODE, &no_set_aspath_prepend_cmd);
38033910
install_element (RMAP_NODE, &no_set_aspath_prepend_val_cmd);
3911+
install_element (RMAP_NODE, &no_set_aspath_exclude_cmd);
3912+
install_element (RMAP_NODE, &no_set_aspath_exclude_val_cmd);
38043913
install_element (RMAP_NODE, &set_origin_cmd);
38053914
install_element (RMAP_NODE, &no_set_origin_cmd);
38063915
install_element (RMAP_NODE, &no_set_origin_val_cmd);

0 commit comments

Comments
 (0)