On Mon, Jun 07, 2010 at 09:33:44PM +0200, Claudio Jeker wrote:
> On Mon, Jun 07, 2010 at 09:12:44PM +0200, Rolf Sommerhalder wrote:
> > > Yeah, the packets are dropped in the POP case of mpls_input.c that's how
> > > far I got until now. I started with a fix but my magic is not strong
> > > enough for now.
> >
> > After taking a look at the source, I essentially backed out changes
> > done in rev. 1.10 /src/usr.sbin/ldpd/kroute.c .
> >
> > Now my test setup works *somehow* even though the LFIB still shows
> > that LDP applies PHP:
> >
> > [r...@p2:root]# ldpctl sh lfib 3.2.1.1
> > flags: * = valid, C = Connected, S = Static
> > Flags Destination Nexthop Local Label Remote Label
> > *R 3.2.1.0/30 2.2.1.2 20 Pop
> >
> >
> > But the kernel routing table is different, e.g. it applies no PHP but
> > does SWAP the labels, as desired :
> >
> > [r...@p2:root]# route -n show -mpls
> > Routing tables
> >
> > MPLS:
> > In label Out label Op Gateway Flags Refs Use
> > Mtu Prio Interface
> > 3 - LOCAL 127.0.0.1 UGT 0 0
> > 33200 56 lo0
> > 16 - LOCAL 10.7.0.254 UGT 0 0
> > - 56 udav0
> > 17 3 SWAP 1.1.2.1 UGT 0 0
> > - 56 vr2
> > 18 3 SWAP 1.1.2.1 UGT 0 30
> > - 56 vr2
> > 19 19 SWAP 1.1.2.1 UGT 0 0
> > - 56 vr2
> > 20 3 SWAP 2.2.1.2 UGT 0 30
> > - 56 vr0 <==
>
> This actually causes the implicit null label to become explicit.
> I don't think this you want that.
>
> > Also, the RTT for the pings is approx. 150 ms (and increasing) which
> > should be in the 1 ms range:
>
> I guess the packet is doing some extra loops.
>
> As I said I know where the problem is but it is far harder to fix then
> expecetd.
>
Here is a fix for the PHP issue. mpls_input() is a bit of spaghetti code
but I think I will fix that later.
--
:wq Claudio
Index: mpls.h
===================================================================
RCS file: /cvs/src/sys/netmpls/mpls.h,v
retrieving revision 1.23
diff -u -p -r1.23 mpls.h
--- mpls.h 2 Jun 2010 15:41:06 -0000 1.23
+++ mpls.h 8 Jun 2010 13:57:05 -0000
@@ -181,7 +181,4 @@ void mpls_input(struct mbuf *);
int mpls_output(struct ifnet *, struct mbuf *, struct sockaddr *,
struct rtentry *);
-void mpls_ip_input(struct mbuf *, u_int8_t);
-void mpls_ip6_input(struct mbuf *, u_int8_t);
-
#endif /* _KERNEL */
Index: mpls_input.c
===================================================================
RCS file: /cvs/src/sys/netmpls/mpls_input.c,v
retrieving revision 1.26
diff -u -p -r1.26 mpls_input.c
--- mpls_input.c 2 Jun 2010 15:41:07 -0000 1.26
+++ mpls_input.c 8 Jun 2010 13:58:43 -0000
@@ -56,6 +56,9 @@ extern int mpls_inkloop;
extern int mpls_mapttl_ip;
extern int mpls_mapttl_ip6;
+int mpls_ip_adjttl(struct mbuf *, u_int8_t);
+int mpls_ip6_adjttl(struct mbuf *, u_int8_t);
+
void
mpls_init(void)
{
@@ -93,7 +96,7 @@ mpls_input(struct mbuf *m)
struct rtentry *rt = NULL;
struct rt_mpls *rt_mpls;
u_int8_t ttl;
- int i, hasbos;
+ int i, s, hasbos;
if (!ISSET(ifp->if_xflags, IFXF_MPLS)) {
m_freem(m);
@@ -117,7 +120,7 @@ mpls_input(struct mbuf *m)
ifp->if_xname, MPLS_LABEL_GET(shim->shim_label),
MPLS_TTL_GET(shim->shim_label),
MPLS_BOS_ISSET(shim->shim_label));
-#endif /* MPLS_DEBUG */
+#endif
/* check and decrement TTL */
ttl = ntohl(shim->shim_label & MPLS_TTL_MASK);
@@ -159,13 +162,23 @@ mpls_input(struct mbuf *m)
* to be at the beginning of the stack.
*/
if (hasbos) {
- mpls_ip_input(m, ttl);
+ if (mpls_ip_adjttl(m, ttl))
+ goto done;
+ s = splnet();
+ IF_INPUT_ENQUEUE(&ipintrq, m);
+ schednetisr(NETISR_IP);
+ splx(s);
goto done;
} else
continue;
case MPLS_LABEL_IPV6NULL:
if (hasbos) {
- mpls_ip6_input(m, ttl);
+ if (mpls_ip6_adjttl(m, ttl))
+ goto done;
+ s = splnet();
+ IF_INPUT_ENQUEUE(&ip6intrq, m);
+ schednetisr(NETISR_IPV6);
+ splx(s);
goto done;
} else
continue;
@@ -208,20 +221,26 @@ mpls_input(struct mbuf *m)
break;
if (!rt->rt_gateway) {
-#ifdef MPLS_DEBUG
- printf("MPLS_DEBUG: no layer 3 informations "
- "attached\n");
-#endif
m_freem(m);
goto done;
}
switch(rt->rt_gateway->sa_family) {
case AF_INET:
- mpls_ip_input(m, ttl);
+ if (mpls_ip_adjttl(m, ttl))
+ break;
+ s = splnet();
+ IF_INPUT_ENQUEUE(&ipintrq, m);
+ schednetisr(NETISR_IP);
+ splx(s);
break;
case AF_INET6:
- mpls_ip6_input(m, ttl);
+ if (mpls_ip6_adjttl(m, ttl))
+ break;
+ s = splnet();
+ IF_INPUT_ENQUEUE(&ip6intrq, m);
+ schednetisr(NETISR_IPV6);
+ splx(s);
break;
default:
m_freem(m);
@@ -229,19 +248,45 @@ mpls_input(struct mbuf *m)
goto done;
case MPLS_OP_POP:
m = mpls_shim_pop(m);
- if (hasbos) {
+ if (!hasbos)
+ /* redo lookup with next label */
+ break;
+
+ ifp = rt->rt_ifp;
#if NMPE > 0
- if (rt->rt_ifp->if_type == IFT_MPLS) {
- smpls = satosmpls(rt_key(rt));
- mpe_input(m, rt->rt_ifp, smpls, ttl);
- goto done;
- }
+ if (ifp->if_type == IFT_MPLS) {
+ smpls = satosmpls(rt_key(rt));
+ mpe_input(m, rt->rt_ifp, smpls, ttl);
+ goto done;
+ }
#endif
- /* last label but we have no clue so drop */
+ if (!rt->rt_gateway) {
m_freem(m);
goto done;
}
- break;
+
+ switch(rt->rt_gateway->sa_family) {
+ case AF_INET:
+ if (mpls_ip_adjttl(m, ttl))
+ goto done;
+ break;
+ case AF_INET6:
+ if (mpls_ip6_adjttl(m, ttl))
+ goto done;
+ break;
+ default:
+ m_freem(m);
+ goto done;
+ }
+
+ /* Output iface is not MPLS-enabled */
+ if (!ISSET(ifp->if_xflags, IFXF_MPLS)) {
+ m_freem(m);
+ goto done;
+ }
+
+ (*ifp->if_ll_output)(ifp, m, rt->rt_gateway, rt);
+ goto done;
case MPLS_OP_PUSH:
m = mpls_shim_push(m, rt_mpls);
break;
@@ -293,27 +338,27 @@ done:
RTFREE(rt);
}
-void
-mpls_ip_input(struct mbuf *m, u_int8_t ttl)
+int
+mpls_ip_adjttl(struct mbuf *m, u_int8_t ttl)
{
struct ip *ip;
- int s, hlen;
+ int hlen;
if (mpls_mapttl_ip) {
if (m->m_len < sizeof (struct ip) &&
(m = m_pullup(m, sizeof(struct ip))) == NULL)
- return;
+ return -1;
ip = mtod(m, struct ip *);
hlen = ip->ip_hl << 2;
if (m->m_len < hlen) {
if ((m = m_pullup(m, hlen)) == NULL)
- return;
+ return -1;
ip = mtod(m, struct ip *);
}
-
+ /* make sure we have a valid header */
if (in_cksum(m, hlen) != 0) {
m_free(m);
- return;
+ return -1;
}
/* set IP ttl from MPLS ttl */
@@ -323,32 +368,23 @@ mpls_ip_input(struct mbuf *m, u_int8_t t
ip->ip_sum = 0;
ip->ip_sum = in_cksum(m, hlen);
}
-
- s = splnet();
- IF_INPUT_ENQUEUE(&ipintrq, m);
- schednetisr(NETISR_IP);
- splx(s);
+ return 0;
}
-void
-mpls_ip6_input(struct mbuf *m, u_int8_t ttl)
+int
+mpls_ip6_adjttl(struct mbuf *m, u_int8_t ttl)
{
struct ip6_hdr *ip6hdr;
- int s;
if (mpls_mapttl_ip6) {
if (m->m_len < sizeof (struct ip6_hdr) &&
(m = m_pullup(m, sizeof(struct ip6_hdr))) == NULL)
- return;
+ return -1;
ip6hdr = mtod(m, struct ip6_hdr *);
/* set IPv6 ttl from MPLS ttl */
ip6hdr->ip6_hlim = ttl;
}
-
- s = splnet();
- IF_INPUT_ENQUEUE(&ip6intrq, m);
- schednetisr(NETISR_IPV6);
- splx(s);
+ return 0;
}