On Wed, Apr 04, 2012 at 10:08:48PM +0200, Rimi Philippe wrote:
> Hi Claudio,
> It works at 90% thanks.
>
> The last 10% are still not working. On PE1 I have 2 Rdomains (20,30) and PE2 1
> rdomain (20). On PE1 I want the rdomain 20 routes to be imported in rdomain 30
> (locally), but that doesn't seem to work locally, here are the details.
>
The last 10% are the hardest ones. The following kernel and bgpd diffs
should do the trick. The kernel diff is needed to forward traffic
directly between mpe(4) interfaces. The bgpd diff makes sure that the MPLS
routes are inserted into the other VPNs on the same router.
This works for me but is not heavily tested please test.
--
:wq Claudio
Index: net/if_mpe.c
===================================================================
RCS file: /cvs/src/sys/net/if_mpe.c,v
retrieving revision 1.26
diff -u -p -r1.26 if_mpe.c
--- net/if_mpe.c 20 Aug 2011 06:21:32 -0000 1.26
+++ net/if_mpe.c 7 Apr 2012 13:44:42 -0000
@@ -145,6 +145,7 @@ mpestart(struct ifnet *ifp)
struct mbuf *m;
struct sockaddr *sa = (struct sockaddr *)&mpedst;
int s;
+ int loop = 0;
sa_family_t af;
struct rtentry *rt;
@@ -166,19 +167,22 @@ mpestart(struct ifnet *ifp)
bcopy(mtod(m, caddr_t), &satosin(sa)->sin_addr,
sizeof(in_addr_t));
m_adj(m, sizeof(in_addr_t));
+ if (satosin(sa)->sin_addr.s_addr == INADDR_LOOPBACK)
+ loop = 1;
break;
default:
m_freem(m);
continue;
}
- rt = rtalloc1(sa, RT_REPORT, 0);
- if (rt == NULL) {
- /* no route give up */
- m_freem(m);
- continue;
+ if (!loop) {
+ rt = rtalloc1(sa, RT_REPORT, 0);
+ if (rt == NULL) {
+ /* no route give up */
+ m_freem(m);
+ continue;
+ }
}
-
#if NBPFILTER > 0
if (ifp->if_bpf) {
/* remove MPLS label before passing packet to bpf */
@@ -191,11 +195,16 @@ mpestart(struct ifnet *ifp)
m->m_pkthdr.len += sizeof(struct shim_hdr);
}
#endif
- /* XXX lie, but mpls_output will only look at sa_family */
- sa->sa_family = AF_MPLS;
-
- mpls_output(rt->rt_ifp, m, sa, rt);
- RTFREE(rt);
+ if (!loop) {
+ /* XXX lie, but mpls_output looks only at sa_family */
+ sa->sa_family = AF_MPLS;
+ mpls_output(rt->rt_ifp, m, sa, rt);
+ RTFREE(rt);
+ } else {
+ /* local packet directly inject into input path */
+ schednetisr(NETISR_MPLS);
+ IF_INPUT_ENQUEUE(&mplsintrq, m);
+ }
}
}
@@ -207,6 +216,7 @@ mpeoutput(struct ifnet *ifp, struct mbuf
int s;
int error;
int off;
+ in_addr_t addr = INADDR_LOOPBACK;
u_int8_t op = 0;
#ifdef DIAGNOSTIC
@@ -248,8 +258,10 @@ mpeoutput(struct ifnet *ifp, struct mbuf
goto out;
}
*mtod(m, sa_family_t *) = AF_INET;
+ if (!rt || rt->rt_flags & RTF_GATEWAY)
+ addr = satosin(dst)->sin_addr.s_addr;
m_copyback(m, sizeof(sa_family_t), sizeof(in_addr_t),
- (caddr_t)&((satosin(dst)->sin_addr)), M_NOWAIT);
+ &addr, M_NOWAIT);
break;
#endif
default:
Index: netmpls/mpls_input.c
===================================================================
RCS file: /cvs/src/sys/netmpls/mpls_input.c,v
retrieving revision 1.32
diff -u -p -r1.32 mpls_input.c
--- netmpls/mpls_input.c 6 Jul 2011 02:42:28 -0000 1.32
+++ netmpls/mpls_input.c 7 Apr 2012 13:45:16 -0000
@@ -101,7 +101,7 @@ mpls_input(struct mbuf *m)
u_int8_t ttl;
int i, s, hasbos;
- if (!ISSET(ifp->if_xflags, IFXF_MPLS)) {
+ if (!ISSET(ifp->if_xflags, IFXF_MPLS) && ifp->if_type != IFT_MPLS) {
m_freem(m);
return;
}
Index: kroute.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/kroute.c,v
retrieving revision 1.188
diff -u -p -r1.188 kroute.c
--- kroute.c 1 May 2011 12:56:04 -0000 1.188
+++ kroute.c 7 Apr 2012 12:40:46 -0000
@@ -2555,7 +2555,7 @@ send_rtmsg(int fd, int action, struct kt
struct {
struct sockaddr_dl dl;
char pad[sizeof(long)];
- } ifp;
+ } ifp, nextifp;
struct sockaddr_mpls mpls;
struct sockaddr_rtlabel label;
int iovcnt = 0;
@@ -2604,6 +2604,17 @@ send_rtmsg(int fd, int action, struct kt
/* adjust iovec */
iov[iovcnt].iov_base = &nexthop;
iov[iovcnt++].iov_len = sizeof(nexthop);
+ } else if (action == RTM_ADD || action == RTM_CHANGE) {
+ bzero(&nextifp, sizeof(nextifp));
+ nextifp.dl.sdl_len = sizeof(struct sockaddr_dl);
+ nextifp.dl.sdl_family = AF_LINK;
+ nextifp.dl.sdl_index = kt->ifindex;
+ /* adjust header */
+ hdr.rtm_addrs |= RTA_GATEWAY;
+ hdr.rtm_msglen += ROUNDUP(sizeof(struct sockaddr_dl));
+ /* adjust iovec */
+ iov[iovcnt].iov_base = &nextifp;
+ iov[iovcnt++].iov_len = ROUNDUP(sizeof(struct sockaddr_dl));
}
bzero(&mask, sizeof(mask));
Index: printconf.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/printconf.c,v
retrieving revision 1.86
diff -u -p -r1.86 printconf.c
--- printconf.c 17 Sep 2011 16:29:44 -0000 1.86
+++ printconf.c 5 Apr 2012 20:56:25 -0000
@@ -35,7 +35,7 @@ void print_mainconf(struct bgpd_config
void print_rdomain_targets(struct filter_set_head *, const char *);
void print_rdomain(struct rdomain *);
const char *print_af(u_int8_t);
-void print_network(struct network_config *);
+void print_network(struct network_config *, const char *);
void print_peer(struct peer_config *, struct bgpd_config *,
const char *);
const char *print_auth_alg(u_int8_t);
@@ -286,14 +286,20 @@ print_rdomain_targets(struct filter_set_
void
print_rdomain(struct rdomain *r)
{
+ struct network *n;
+
printf("rdomain %u {\n", r->rtableid);
- printf("\tdescr \"%s\"\n", r->descr);
+ if (*r->descr)
+ printf("\tdescr \"%s\"\n", r->descr);
if (r->flags & F_RIB_NOFIBSYNC)
printf("\tfib-update no\n");
else
printf("\tfib-update yes\n");
printf("\tdepend on %s\n", r->ifmpe);
+ TAILQ_FOREACH(n, &r->net_l, entry)
+ print_network(&n->net, "\t");
+
printf("\n\t%s\n", log_rd(r->rd));
print_rdomain_targets(&r->export, "export-target");
@@ -318,17 +324,17 @@ print_af(u_int8_t aid)
}
void
-print_network(struct network_config *n)
+print_network(struct network_config *n, const char *c)
{
switch (n->type) {
case NETWORK_STATIC:
- printf("network %s static", print_af(n->prefix.aid));
+ printf("%snetwork %s static", c, print_af(n->prefix.aid));
break;
case NETWORK_CONNECTED:
- printf("network %s connected", print_af(n->prefix.aid));
+ printf("%snetwork %s connected", c, print_af(n->prefix.aid));
break;
default:
- printf("network %s/%u", log_addr(&n->prefix), n->prefixlen);
+ printf("%snetwork %s/%u", c, log_addr(&n->prefix),
n->prefixlen);
break;
}
if (!TAILQ_EMPTY(&n->attrset))
@@ -716,7 +722,7 @@ print_config(struct bgpd_config *conf, s
print_mainconf(conf);
printf("\n");
TAILQ_FOREACH(n, net_l, entry)
- print_network(&n->net);
+ print_network(&n->net, "");
printf("\n");
SIMPLEQ_FOREACH(rd, rdom_l, entry)
print_rdomain(rd);
Index: rde.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/rde.c,v
retrieving revision 1.313
diff -u -p -r1.313 rde.c
--- rde.c 7 Apr 2012 17:25:51 -0000 1.313
+++ rde.c 7 Apr 2012 17:27:50 -0000
@@ -2377,15 +2377,11 @@ rde_send_kroute(struct prefix *new, stru
struct rdomain *rd;
enum imsg_type type;
- /*
- * Make sure that self announce prefixes are not commited to the
- * FIB. If both prefixes are unreachable no update is needed.
- */
- if ((old == NULL || old->aspath->flags & F_PREFIX_ANNOUNCED) &&
- (new == NULL || new->aspath->flags & F_PREFIX_ANNOUNCED))
+ /* If both prefixes are unreachable no update is needed. */
+ if (old == NULL && new == NULL)
return;
-
- if (new == NULL || new->aspath->flags & F_PREFIX_ANNOUNCED) {
+ /* select if the prefix needs to be removed or updated */
+ if (new == NULL) {
type = IMSG_KROUTE_DELETE;
p = old;
} else {
@@ -2393,15 +2389,18 @@ rde_send_kroute(struct prefix *new, stru
p = new;
}
+ /* setup kroute struct to be passed */
pt_getaddr(p->prefix, &addr);
bzero(&kr, sizeof(kr));
memcpy(&kr.prefix, &addr, sizeof(kr.prefix));
kr.prefixlen = p->prefix->prefixlen;
+
+ /* the following values are only used in the IMSG_KROUTE_CHANGE case */
if (p->aspath->flags & F_NEXTHOP_REJECT)
kr.flags |= F_REJECT;
if (p->aspath->flags & F_NEXTHOP_BLACKHOLE)
kr.flags |= F_BLACKHOLE;
- if (type == IMSG_KROUTE_CHANGE)
+ if (p->aspath->nexthop)
memcpy(&kr.nexthop, &p->aspath->nexthop->true_nexthop,
sizeof(kr.nexthop));
strlcpy(kr.label, rtlabel_id2name(p->aspath->rtlabelid),
@@ -2409,26 +2408,59 @@ rde_send_kroute(struct prefix *new, stru
switch (addr.aid) {
case AID_VPN_IPv4:
- if (ribid != 1)
+ if (ribid != 1) /* XXX magic number */
/* not Loc-RIB, no update for VPNs */
break;
SIMPLEQ_FOREACH(rd, rdomains_l, entry) {
- if (!rde_rdomain_import(p->aspath, rd))
- continue;
- /* must send exit_nexthop so that correct MPLS tunnel
+ enum imsg_type rdtype = type;
+
+ /* don't loop update back to own rdomain, see below */
+ if (p->aspath->flags & F_PREFIX_ANNOUNCED &&
+ rd->rd == addr.vpn4.rd) {
+ if (rdtype == IMSG_KROUTE_DELETE)
+ continue;
+ rdtype = IMSG_KROUTE_DELETE;
+ }
+
+ /*
+ * Check if prefix should be imported.
+ * If not and it is an update and the old
+ * prefix was imported then it must be removed.
+ */
+ if (!rde_rdomain_import(p->aspath, rd)) {
+ if (rdtype == IMSG_KROUTE_CHANGE && old &&
+ rde_rdomain_import(old->aspath, rd))
+ rdtype = IMSG_KROUTE_DELETE;
+ else
+ continue;
+ }
+ /*
+ * Must send exit_nexthop so that correct MPLS tunnel
* is chosen
*/
- if (type == IMSG_KROUTE_CHANGE)
+ if (p->aspath->nexthop)
memcpy(&kr.nexthop,
&p->aspath->nexthop->exit_nexthop,
sizeof(kr.nexthop));
- if (imsg_compose(ibuf_main, type, rd->rtableid, 0, -1,
+ if (imsg_compose(ibuf_main, rdtype, rd->rtableid, 0, -1,
&kr, sizeof(kr)) == -1)
fatal("imsg_compose error");
}
break;
default:
+ /*
+ * Make sure that self announce prefixes are not commited to
+ * the FIB. In case the new prefix is self announced remove the
+ * old prefix instead. In case it is already a delete nothing
+ * needs to be done.
+ */
+ if (p->aspath->flags & F_PREFIX_ANNOUNCED) {
+ if (type == IMSG_KROUTE_DELETE)
+ return;
+ type = IMSG_KROUTE_DELETE;
+ }
+
if (imsg_compose(ibuf_main, type, ribs[ribid].rtableid, 0, -1,
&kr, sizeof(kr)) == -1)
fatal("imsg_compose error");
Index: rde_rib.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/rde_rib.c,v
retrieving revision 1.131
diff -u -p -r1.131 rde_rib.c
--- rde_rib.c 21 Sep 2011 08:59:01 -0000 1.131
+++ rde_rib.c 5 Apr 2012 21:40:37 -0000
@@ -1106,7 +1106,8 @@ nexthop_modify(struct rde_aspath *asp, s
{
struct nexthop *nh;
- if (type == ACTION_SET_NEXTHOP && aid != nexthop->aid)
+ if (type == ACTION_SET_NEXTHOP && aid != nexthop->aid &&
+ !(nexthop->aid == AID_INET && aid == AID_VPN_IPv4))
return;
asp->flags &= ~F_NEXTHOP_MASK;