[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: I may get punked for this ..



On Fri, Aug 20, 2004 at 04:38:35PM +0200, Henning Brauer wrote:
> * Per Engelbrecht <per_(_at_)_xterm_(_dot_)_dk> [2004-08-20 16:32]:

...

> > > One bug that remains: prepend-self works the wrong way, prepending
> > > on updates received, rather than on updates sent to (eBGP) peers;
> > > that's usually not what one wants.
> > No, it's not.  I'm sure Henning will have it fixed sometime soon.
> 
> actually, claudio is fixing it as we speak.
> It is not really a bug, it is a little unexpected semantic. but we are 
> doing soem changes to have this work like expected.
> 

And here is the patch to fix this. Please test and report if this fixes
your problem. This also adds the possibility to prepend AS pathes with the
remote neighbor-as.

-- 
:wq Claudio

Index: bgpd.conf.5
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/bgpd.conf.5,v
retrieving revision 1.36
diff -u -p -r1.36 bgpd.conf.5
--- bgpd.conf.5	19 Aug 2004 16:12:31 -0000	1.36
+++ bgpd.conf.5	20 Aug 2004 12:12:41 -0000
@@ -812,6 +812,12 @@ Add the prefix in the update to the spec
 radix table, regardless of whether or not the path was selected for routing.
 This option may be useful in building realtime blacklists.
 .Pp
+.It Ic prepend-neighbor Ar number
+Prepend the remote neighbor AS
+.Ar number
+times to the
+.Em AS path .
+.Pp
 .It Ic prepend-self Ar number
 Prepend the local AS
 .Ar number
Index: bgpd.h
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/bgpd.h,v
retrieving revision 1.140
diff -u -p -r1.140 bgpd.h
--- bgpd.h	10 Aug 2004 13:02:07 -0000	1.140
+++ bgpd.h	20 Aug 2004 14:25:19 -0000
@@ -158,15 +158,16 @@ enum enforce_as {
 
 struct filter_set {
 	u_int16_t		flags;
+	u_int8_t		prepend_self;
+	u_int8_t		prepend_peer;
 	u_int32_t		localpref;
 	u_int32_t		med;
 	struct bgpd_addr	nexthop;
-	u_int8_t		prepend;
-	char			pftable[PFTABLE_LEN];
 	struct {
 		int		as;
 		int		type;
 	} community;
+	char			pftable[PFTABLE_LEN];
 };
 
 enum auth_method {
@@ -452,7 +453,9 @@ enum filter_actions {
 
 enum directions {
 	DIR_IN=1,
-	DIR_OUT
+	DIR_OUT,
+	DIR_DEFAULT_IN,		/* only needed to apply default set */
+	DIR_DEFAULT_OUT
 };
 
 enum from_spec {
@@ -478,8 +481,8 @@ enum comp_ops {
 #define	SET_LOCALPREF		0x0001
 #define	SET_MED			0x0002
 #define	SET_NEXTHOP		0x0004
-#define	SET_NEXTHOP6		0x0008
-#define	SET_PREPEND		0x0010
+#define	SET_PREPEND_SELF	0x0008
+#define	SET_PREPEND_PEER	0x0010
 #define	SET_PFTABLE		0x0020
 #define	SET_COMMUNITY		0x0040
 #define	SET_NEXTHOP_REJECT	0x0080
Index: parse.y
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/parse.y,v
retrieving revision 1.134
diff -u -p -r1.134 parse.y
--- parse.y	17 Aug 2004 16:06:39 -0000	1.134
+++ parse.y	18 Aug 2004 14:33:03 -0000
@@ -147,7 +147,8 @@ typedef struct {
 %token	QUICK
 %token	FROM TO ANY
 %token	PREFIX PREFIXLEN SOURCEAS TRANSITAS COMMUNITY
-%token	SET LOCALPREF MED METRIC NEXTHOP PREPEND PFTABLE REJECT BLACKHOLE
+%token	SET LOCALPREF MED METRIC NEXTHOP REJECT BLACKHOLE
+%token	PREPEND_SELF PREPEND_PEER PFTABLE
 %token	ERROR
 %token	IPSEC ESP AH SPI IKE
 %token	<v.string>		STRING
@@ -1086,13 +1087,21 @@ filter_set_opt	: LOCALPREF number		{
 		| NEXTHOP REJECT		{
 			$$.flags |= SET_NEXTHOP_REJECT;
 		}
-		| PREPEND number		{
-			$$.flags = SET_PREPEND;
+		| PREPEND_SELF number		{
+			$$.flags = SET_PREPEND_SELF;
 			if ($2 > 128) {
 				yyerror("to many prepends");
 				YYERROR;
 			}
-			$$.prepend = $2;
+			$$.prepend_self = $2;
+		}
+		| PREPEND_PEER number		{
+			$$.flags = SET_PREPEND_PEER;
+			if ($2 > 128) {
+				yyerror("to many prepends");
+				YYERROR;
+			}
+			$$.prepend_peer = $2;
 		}
 		| PFTABLE string		{
 			$$.flags = SET_PFTABLE;
@@ -1237,7 +1246,8 @@ lookup(char *s)
 		{ "pftable",		PFTABLE},
 		{ "prefix",		PREFIX},
 		{ "prefixlen",		PREFIXLEN},
-		{ "prepend-self",	PREPEND},
+		{ "prepend-neighbor",	PREPEND_PEER},
+		{ "prepend-self",	PREPEND_SELF},
 		{ "quick",		QUICK},
 		{ "reject",		REJECT},
 		{ "remote-as",		REMOTEAS},
@@ -1953,8 +1963,10 @@ merge_filterset(struct filter_set *a, st
 	if (b->flags & SET_NEXTHOP)
 		memcpy(&a->nexthop, &b->nexthop,
 		    sizeof(a->nexthop));
-	if (b->flags & SET_PREPEND)
-		a->prepend = b->prepend;
+	if (b->flags & SET_PREPEND_SELF)
+		a->prepend_self = b->prepend_self;
+	if (b->flags & SET_PREPEND_PEER)
+		a->prepend_peer = b->prepend_peer;
 	if (b->flags & SET_PFTABLE)
 		strlcpy(a->pftable, b->pftable,
 		    sizeof(a->pftable));
Index: printconf.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/printconf.c,v
retrieving revision 1.27
diff -u -p -r1.27 printconf.c
--- printconf.c	13 Aug 2004 14:03:20 -0000	1.27
+++ printconf.c	19 Aug 2004 11:26:39 -0000
@@ -83,8 +83,10 @@ print_set(struct filter_set *set)
 			printf("nexthop reject ");
 		if (set->flags & SET_NEXTHOP_BLACKHOLE)
 			printf("nexthop blackhole ");
-		if (set->flags & SET_PREPEND)
-			printf("prepend-self %u ", set->prepend);
+		if (set->flags & SET_PREPEND_SELF)
+			printf("prepend-self %u ", set->prepend_self);
+		if (set->flags & SET_PREPEND_PEER)
+			printf("prepend-neighbor %u ", set->prepend_peer);
 		printf("}");
 	}
 }
Index: rde.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/rde.c,v
retrieving revision 1.142
diff -u -p -r1.142 rde.c
--- rde.c	12 Aug 2004 10:24:16 -0000	1.142
+++ rde.c	20 Aug 2004 14:31:32 -0000
@@ -680,7 +680,7 @@ rde_update_dispatch(struct imsg *imsg)
 	}
 
 	/* apply default overrides */
-	rde_apply_set(asp, &peer->conf.attrset, AF_INET);
+	rde_apply_set(asp, &peer->conf.attrset, AF_INET, peer, DIR_DEFAULT_IN);
 
 	/* parse nlri prefix */
 	while (nlri_len > 0) {
@@ -756,7 +756,8 @@ rde_update_dispatch(struct imsg *imsg)
 		mplen -= pos;
 
 		/* apply default overrides */
-		rde_apply_set(asp, &peer->conf.attrset, AF_INET6);
+		rde_apply_set(asp, &peer->conf.attrset, AF_INET6, peer,
+		    DIR_DEFAULT_IN);
 
 		switch (afi) {
 		case AFI_IPv6:
@@ -1944,13 +1945,15 @@ network_add(struct network_config *nc, i
 	    F_ATTR_LOCALPREF | F_PREFIX_ANNOUNCED;
 	/* the nexthop is unset unless a default set overrides it */
 
-	/* apply default overrides */
-	rde_apply_set(asp, &nc->attrset, nc->prefix.af);
-
-	if (flagstatic)
+	if (flagstatic) {
+		rde_apply_set(asp, &nc->attrset, nc->prefix.af, &peerself,
+		    DIR_DEFAULT_IN);
 		path_update(&peerself, asp, &nc->prefix, nc->prefixlen);
-	else
+	} else {
+		rde_apply_set(asp, &nc->attrset, nc->prefix.af, &peerdynamic,
+		    DIR_DEFAULT_IN);
 		path_update(&peerdynamic, asp, &nc->prefix, nc->prefixlen);
+	}
 }
 
 void
Index: rde.h
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/rde.h,v
retrieving revision 1.55
diff -u -p -r1.55 rde.h
--- rde.h	13 Aug 2004 14:03:20 -0000	1.55
+++ rde.h	20 Aug 2004 14:32:00 -0000
@@ -346,7 +346,7 @@ void		 pt_dump(void (*)(struct pt_entry 
 enum filter_actions rde_filter(struct rde_peer *, struct rde_aspath *,
     struct bgpd_addr *, u_int8_t, enum directions);
 void		 rde_apply_set(struct rde_aspath *, struct filter_set *,
-		     sa_family_t);
+		     sa_family_t, struct rde_peer *, enum directions);
 int		 rde_filter_community(struct rde_aspath *, int, int);
 
 #endif /* __RDE_H__ */
Index: rde_filter.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/rde_filter.c,v
retrieving revision 1.18
diff -u -p -r1.18 rde_filter.c
--- rde_filter.c	10 Aug 2004 13:02:08 -0000	1.18
+++ rde_filter.c	20 Aug 2004 14:30:29 -0000
@@ -45,7 +45,7 @@ rde_filter(struct rde_peer *peer, struct
 		    f->peer.peerid != peer->conf.id)
 			continue;
 		if (rde_filter_match(f, asp, prefix, prefixlen)) {
-			rde_apply_set(asp, &f->set, prefix->af);
+			rde_apply_set(asp, &f->set, prefix->af, asp->peer, dir);
 			if (f->action != ACTION_NONE)
 				action = f->action;
 			if (f->quick)
@@ -56,14 +56,40 @@ rde_filter(struct rde_peer *peer, struct
 }
 
 void
-rde_apply_set(struct rde_aspath *asp, struct filter_set *set, sa_family_t af)
+rde_apply_set(struct rde_aspath *asp, struct filter_set *set, sa_family_t af,
+    struct rde_peer *peer, enum directions dir) 
 {
 	struct aspath	*new;
 	u_int16_t	 as;
+	u_int8_t	 prepend;
 
 	if (asp == NULL)
 		return;
 
+	if (set->flags & SET_PREPEND_SELF && dir != DIR_DEFAULT_IN) {
+		/* don't apply if this is a incomming default override */
+		as = rde_local_as();
+		prepend = set->prepend_self;
+		new = aspath_prepend(asp->aspath, as, prepend);
+		aspath_put(asp->aspath);
+		asp->aspath = new;
+	}
+
+	if (dir == DIR_DEFAULT_OUT)
+		/*
+		 * default outgoing overrides are only allowed to
+		 * set prepend-self
+		 */
+		return;
+
+	if (set->flags & SET_PREPEND_PEER) {
+		as = peer->conf.remote_as;
+		prepend = set->prepend_peer;
+		new = aspath_prepend(asp->aspath, as, prepend);
+		aspath_put(asp->aspath);
+		asp->aspath = new;
+	}
+
 	if (set->flags & SET_LOCALPREF)
 		asp->lpref = set->localpref;
 	if (set->flags & SET_MED) {
@@ -73,12 +99,6 @@ rde_apply_set(struct rde_aspath *asp, st
 
 	nexthop_modify(asp, &set->nexthop, set->flags, af);
 
-	if (set->flags & SET_PREPEND) {
-		as = rde_local_as();
-		new = aspath_prepend(asp->aspath, as, set->prepend);
-		aspath_put(asp->aspath);
-		asp->aspath = new;
-	}
 	if (set->flags & SET_PFTABLE)
 		strlcpy(asp->pftable, set->pftable, sizeof(asp->pftable));
 	if (set->flags & SET_COMMUNITY) {
Index: rde_update.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/rde_update.c,v
retrieving revision 1.29
diff -u -p -r1.29 rde_update.c
--- rde_update.c	13 Aug 2004 14:03:20 -0000	1.29
+++ rde_update.c	20 Aug 2004 14:44:29 -0000
@@ -334,6 +334,8 @@ up_generate_updates(struct rde_peer *pee
 		/* copy attributes for output filter */
 		fasp = path_copy(old->aspath);
 
+		/* default override not needed here as this is a withdraw */
+		
 		pt_getaddr(old->prefix, &addr);
 		if (rde_filter(peer, fasp, &addr,
 		    old->prefix->prefixlen, DIR_OUT) == ACTION_DENY) {
@@ -431,6 +433,13 @@ up_generate_updates(struct rde_peer *pee
 		/* copy attributes for output filter */
 		fasp = path_copy(new->aspath);
 
+		/*
+		 * apply default outgoing overrides,
+		 * acctually only prepend-self
+		 */
+		rde_apply_set(fasp, &peer->conf.attrset, new->prefix->af,
+		    fasp->peer, DIR_DEFAULT_OUT);
+
 		pt_getaddr(new->prefix, &addr);
 		if (rde_filter(peer, fasp, &addr,
 		    new->prefix->prefixlen, DIR_OUT) == ACTION_DENY) {