Hi,

I am trying to make IPv6 over VPLS.
I updated ldpd(8) to install MPLS route for IPv6 nexthop. I can see the routes
but when pinging the destination I get "No route to host". Can someone give me a
pointer for the next step ?

Thank you in advance,
Denis

* Without the patch :

mpls1# route -n show 
Routing tables

Internet:
Destination        Gateway            Flags   Refs      Use   Mtu  Prio Iface
[...]
172.16.0/24        192.168.150.139    UGT        0        6     -    32 vio0 

Internet6:
Destination                        Gateway                        Flags   Refs  
    Use   Mtu  Prio Iface
[...]
2001:db8::/64                      fe80::fcd8:d9ff:fe57:bd48%vio0 UG         0  
      4     -    32 vio0 
2001:db8:1::/64                    2001:db8:1::1                  UCn        0  
      0     -     4 vether0
2001:db8:1::1                      fe:e1:ba:d0:89:89              UHLl       0  
     76     -     1 vether0
2001:db8:fffe::/64                 fe80::fcd8:d9ff:fe57:bd48%vio0 UG         1  
      6     -    32 vio0 
2001:db8:ffff::/64                 2001:db8:ffff::1               UCn        1  
      2     -     4 vio0 
2001:db8:ffff::/64                 link#1                         UC         0  
      0     -    32 vio0 
2001:db8:ffff::1                   9e:21:8a:77:cd:cc              UHLl       0  
   1511     -     1 vio0 
2001:db8:ffff::2                   fe:d8:d9:57:bd:48              UHLc       0  
    257     -     3 vio0 

MPLS:
In label  Out label Op     Gateway            Flags   Refs      Use   Mtu  Prio 
Interface
17        -         POP    192.168.150.139    UGT        0        0     -    32 
vio0 
18        16        SWAP   192.168.150.139    UGT        0        0     -    32 
vio0 

mpls1# route get 2001:db8::/64
   route to: 2001:db8::
destination: 2001:db8::
       mask: ffff:ffff:ffff:ffff::
    gateway: fe80::fcd8:d9ff:fe57:bd48%vio0
  interface: vio0
 if address: fe80::9c21:8aff:fe77:cdcc%vio0
   priority: 32 (ospf)
      flags: <UP,GATEWAY,DONE>
     use       mtu    expire
       4         0         0 

mpls1# ping6 2001:db8::1
PING 2001:db8::1 (2001:db8::1): 56 data bytes
64 bytes from 2001:db8::1: icmp_seq=0 hlim=63 time=1.039 ms
64 bytes from 2001:db8::1: icmp_seq=1 hlim=63 time=1.037 ms
^C
--- 2001:db8::1 ping statistics ---
2 packets transmitted, 2 packets received, 0.0% packet loss
round-trip min/avg/max/std-dev = 1.037/1.038/1.039/0.001 ms

* With the patch :

mpls1# route -n show           
Routing tables

Internet:
Destination        Gateway            Flags   Refs      Use   Mtu  Prio Iface
[...]
172.16.0/24        192.168.150.139    UGT        0        6     -    32 vio0 

Internet6:
Destination                        Gateway                        Flags   Refs  
    Use   Mtu  Prio Iface
[...]
2001:db8::/64                      fe80::fcd8:d9ff:fe57:bd48%vio0 UGT        0  
      4     -    32 vio0 
2001:db8:1::/64                    2001:db8:1::1                  UCn        0  
      0     -     4 vether0
2001:db8:1::1                      fe:e1:ba:d0:89:89              UHLl       0  
     76     -     1 vether0
2001:db8:fffe::/64                 fe80::fcd8:d9ff:fe57:bd48%vio0 UG         2  
      7     -    32 vio0 
2001:db8:ffff::/64                 2001:db8:ffff::1               UCn        1  
      2     -     4 vio0 
2001:db8:ffff::/64                 link#1                         UC         0  
      0     -    32 vio0 
2001:db8:ffff::1                   9e:21:8a:77:cd:cc              UHLl       0  
   1526     -     1 vio0 
2001:db8:ffff::2                   fe:d8:d9:57:bd:48              UHLc       0  
    281     -     3 vio0 

MPLS:
In label  Out label Op     Gateway            Flags   Refs      Use   Mtu  Prio 
Interface
17        -         POP    192.168.150.139    UGT        0        0     -    32 
vio0 
18        16        SWAP   192.168.150.139    UGT        0        0     -    32 
vio0 
19        18        SWAP   fe80::fcd8:d9ff:fe57:bd48%vio0 UGT        0        0 
    -    32 vio0 
20        -         POP    fe80::fcd8:d9ff:fe57:bd48%vio0 UGT        0        0 
    -    32 vio0 
21        -         LOCAL  ::1%3              UGT        0        0 32768     8 
lo0  
22        -         LOCAL  ::1%3              UGT        0        0 32768     8 
lo0  
23        -         LOCAL  ::1%3              UGT        0        0 32768     8 
lo0  
24        -         LOCAL  ::1%3              UGT        0        0 32768     8 
lo0

mpls1# route get 2001:db8::/64 
   route to: 2001:db8::
destination: 2001:db8::
       mask: ffff:ffff:ffff:ffff::
    gateway: fe80::fcd8:d9ff:fe57:bd48%vio0
  interface: vio0
 if address: fe80::9c21:8aff:fe77:cdcc%vio0
 mpls label: PUSH 18
   priority: 32 (ospf)
      flags: <UP,GATEWAY,DONE,MPLS>
     use       mtu    expire
       4         0         0 
sockaddrs: <DST,GATEWAY,NETMASK,IFP,IFA,SRC>

mpls1# ping6 2001:db8::1 
PING 2001:db8::1 (2001:db8::1): 56 data bytes
ping6: sendmsg: No route to host
ping: wrote 2001:db8::1 64 chars, ret=-1
ping6: sendmsg: No route to host
ping: wrote 2001:db8::1 64 chars, ret=-1
ping6: sendmsg: No route to host
ping: wrote 2001:db8::1 64 chars, ret=-1
^C
--- 2001:db8::1 ping statistics ---
3 packets transmitted, 0 packets received, 100.0% packet loss

* Patch :

Index: kroute.c
===================================================================
RCS file: /cvs/src/usr.sbin/ldpd/kroute.c,v
retrieving revision 1.66
diff -u -p -r1.66 kroute.c
--- kroute.c    24 Jul 2017 11:00:01 -0000      1.66
+++ kroute.c    27 Dec 2017 12:48:59 -0000
@@ -259,7 +259,7 @@ kr_change(struct kroute *kr)
 
        if (ldp_addrisset(kn->r.af, &kn->r.nexthop) &&
            kn->r.remote_label != NO_LABEL) {
-               if (send_rtmsg(kr_state.fd, RTM_CHANGE, &kn->r, AF_INET) == -1)
+               if (send_rtmsg(kr_state.fd, RTM_CHANGE, &kn->r, kn->r.af) == -1)
                        return (-1);
        }
 
@@ -305,7 +305,7 @@ kr_delete(struct kroute *kr)
        kn->r.remote_label = NO_LABEL;
 
        if (update &&
-           send_rtmsg(kr_state.fd, RTM_CHANGE, &kn->r, AF_INET) == -1)
+           send_rtmsg(kr_state.fd, RTM_CHANGE, &kn->r, kn->r.af) == -1)
                return (-1);
 
        return (0);
@@ -346,7 +346,7 @@ kr_fib_couple(void)
                        if (ldp_addrisset(kn->r.af, &kn->r.nexthop) &&
                            kn->r.remote_label != NO_LABEL) {
                                send_rtmsg(kr_state.fd, RTM_CHANGE,
-                                   &kn->r, AF_INET);
+                                   &kn->r, kn->r.af);
                        }
                }
        }
@@ -387,7 +387,7 @@ kr_fib_decouple(void)
                                rl = kn->r.remote_label;
                                kn->r.remote_label = NO_LABEL;
                                send_rtmsg(kr_state.fd, RTM_CHANGE,
-                                   &kn->r, AF_INET);
+                                   &kn->r, kn->r.af);
                                kn->r.remote_label = rl;
                        }
                }
@@ -1311,6 +1311,145 @@ send_rtmsg_v4(int fd, int action, struct
 static int
 send_rtmsg_v6(int fd, int action, struct kroute *kr, int family)
 {
+       struct iovec            iov[5];
+       struct rt_msghdr        hdr;
+       struct sockaddr_mpls    label_in, label_out;
+       struct sockaddr_in6     dst, mask, nexthop;
+       int                     iovcnt = 0;
+
+       if (kr_state.fib_sync == 0)
+               return (0);
+
+       /*
+        * Reserved labels (implicit and explicit NULL) should not be added
+        * to the FIB.
+        */
+       if (family == AF_MPLS && kr->local_label < MPLS_LABEL_RESERVED_MAX)
+               return (0);
+
+       /* initialize header */
+       memset(&hdr, 0, sizeof(hdr));
+       hdr.rtm_version = RTM_VERSION;
+
+       hdr.rtm_type = action;
+       hdr.rtm_flags = RTF_UP;
+       hdr.rtm_fmask = RTF_MPLS;
+       hdr.rtm_seq = kr_state.rtseq++; /* overflow doesn't matter */
+       hdr.rtm_msglen = sizeof(hdr);
+       hdr.rtm_hdrlen = sizeof(struct rt_msghdr);
+       hdr.rtm_priority = kr->priority;
+       hdr.rtm_tableid = kr_state.rdomain;     /* rtableid */
+       /* adjust iovec */
+       iov[iovcnt].iov_base = &hdr;
+       iov[iovcnt++].iov_len = sizeof(hdr);
+
+       if (family == AF_MPLS) {
+               memset(&label_in, 0, sizeof(label_in));
+               label_in.smpls_len = sizeof(label_in);
+               label_in.smpls_family = AF_MPLS;
+               label_in.smpls_label =
+                   htonl(kr->local_label << MPLS_LABEL_OFFSET);
+               /* adjust header */
+               hdr.rtm_flags |= RTF_MPLS | RTF_MPATH;
+               hdr.rtm_addrs |= RTA_DST;
+               hdr.rtm_msglen += sizeof(label_in);
+               /* adjust iovec */
+               iov[iovcnt].iov_base = &label_in;
+               iov[iovcnt++].iov_len = sizeof(label_in);
+       } else {
+               memset(&dst, 0, sizeof(dst));
+               dst.sin6_len = sizeof(dst);
+               dst.sin6_family = AF_INET6;
+               dst.sin6_addr = kr->prefix.v6;
+               /* adjust header */
+               hdr.rtm_addrs |= RTA_DST;
+               hdr.rtm_msglen += ROUNDUP(sizeof(dst));
+               /* adjust iovec */
+               iov[iovcnt].iov_base = &dst;
+               iov[iovcnt++].iov_len = ROUNDUP(sizeof(dst));
+       }
+
+       memset(&nexthop, 0, sizeof(nexthop));
+       nexthop.sin6_len = sizeof(nexthop);
+       nexthop.sin6_family = AF_INET6;
+       nexthop.sin6_addr = kr->nexthop.v6;
+       nexthop.sin6_scope_id = kr->ifindex;
+       /*
+        * XXX we should set the sin6_scope_id but the kernel
+        * XXX does not expect it that way. It must be fiddled
+        * XXX into the sin6_addr. Welcome to the typical
+        * XXX IPv6 insanity and all without wine bottles.
+       */
+       embedscope(&nexthop);
+
+       /* adjust header */
+       hdr.rtm_flags |= RTF_GATEWAY;
+       hdr.rtm_addrs |= RTA_GATEWAY;
+       hdr.rtm_msglen += ROUNDUP(sizeof(nexthop));
+       /* adjust iovec */
+       iov[iovcnt].iov_base = &nexthop;
+       iov[iovcnt++].iov_len = ROUNDUP(sizeof(nexthop));
+
+       if (family == AF_INET6) {
+               memset(&mask, 0, sizeof(mask));
+               mask.sin6_len = sizeof(mask);
+               mask.sin6_family = AF_INET6;
+               mask.sin6_addr = *prefixlen2mask6(kr->prefixlen);
+               /* adjust header */
+               if (kr->prefixlen == 128)
+                       hdr.rtm_flags |= RTF_HOST;
+               hdr.rtm_addrs |= RTA_NETMASK;
+               hdr.rtm_msglen += ROUNDUP(sizeof(mask));
+               /* adjust iovec */
+               iov[iovcnt].iov_base = &mask;
+               iov[iovcnt++].iov_len = ROUNDUP(sizeof(mask));
+       }
+
+       /* If action is RTM_DELETE we have to get rid of MPLS infos */
+       if (kr->remote_label != NO_LABEL && action != RTM_DELETE) {
+               memset(&label_out, 0, sizeof(label_out));
+               label_out.smpls_len = sizeof(label_out);
+               label_out.smpls_family = AF_MPLS;
+               label_out.smpls_label =
+                   htonl(kr->remote_label << MPLS_LABEL_OFFSET);
+               /* adjust header */
+               hdr.rtm_addrs |= RTA_SRC;
+               hdr.rtm_flags |= RTF_MPLS;
+               hdr.rtm_msglen += sizeof(label_out);
+               /* adjust iovec */
+               iov[iovcnt].iov_base = &label_out;
+               iov[iovcnt++].iov_len = sizeof(label_out);
+
+               if (kr->remote_label == MPLS_LABEL_IMPLNULL) {
+                       if (family == AF_MPLS)
+                               hdr.rtm_mpls = MPLS_OP_POP;
+                       else
+                               return (0);
+               } else {
+                       if (family == AF_MPLS)
+                               hdr.rtm_mpls = MPLS_OP_SWAP;
+                       else
+                               hdr.rtm_mpls = MPLS_OP_PUSH;
+               }
+       }
+
+ retry:
+       if (writev(fd, iov, iovcnt) == -1) {
+               if (errno == ESRCH) {
+                       if (hdr.rtm_type == RTM_CHANGE && family == AF_MPLS) {
+                               hdr.rtm_type = RTM_ADD;
+                               goto retry;
+                       } else if (hdr.rtm_type == RTM_DELETE) {
+                               log_info("route %s/%u vanished before delete",
+                                   log_addr(kr->af, &kr->prefix), 
kr->prefixlen);
+                               return (-1);
+                       }
+               }
+               log_warn("%s action %u, af %s, prefix %s/%u", __func__,
+                   hdr.rtm_type, af_name(family), log_addr(kr->af, 
&kr->prefix), 
+                   kr->prefixlen);
+               return (-1);
+       }
        return (0);
 }
 

Reply via email to