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;
 }

Reply via email to