The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netmpls/mpls_output.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /* $OpenBSD: mpls_output.c,v 1.28 2019/09/03 10:39:08 jsg Exp $ */
    2 
    3 /*
    4  * Copyright (c) 2008 Claudio Jeker <claudio@openbsd.org>
    5  * Copyright (c) 2008 Michele Marchetto <michele@openbsd.org>
    6  *
    7  * Permission to use, copy, modify, and distribute this software for any
    8  * purpose with or without fee is hereby granted, provided that the above
    9  * copyright notice and this permission notice appear in all copies.
   10  *
   11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   18  */
   19 
   20 #include <sys/param.h>
   21 #include <sys/mbuf.h>
   22 #include <sys/systm.h>
   23 #include <sys/socket.h>
   24 
   25 #include <net/if.h>
   26 #include <net/if_var.h>
   27 #include <net/route.h>
   28 
   29 #include <netmpls/mpls.h>
   30 
   31 #include <netinet/in.h>
   32 #include <netinet/ip.h>
   33 
   34 #ifdef INET6
   35 #include <netinet/ip6.h>
   36 #endif
   37 
   38 #ifdef MPLS_DEBUG
   39 #define MPLS_LABEL_GET(l)       ((ntohl((l) & MPLS_LABEL_MASK)) >> MPLS_LABEL_OFFSET)
   40 #endif
   41 
   42 void            mpls_do_cksum(struct mbuf *);
   43 u_int8_t        mpls_getttl(struct mbuf *, sa_family_t);
   44 
   45 int
   46 mpls_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
   47     struct rtentry *rt)
   48 {
   49         struct sockaddr_mpls    *smpls;
   50         struct sockaddr_mpls     sa_mpls;
   51         struct shim_hdr         *shim;
   52         struct rt_mpls          *rt_mpls;
   53         int                      error;
   54         u_int8_t                 ttl;
   55 
   56         if (rt == NULL || (dst->sa_family != AF_INET &&
   57             dst->sa_family != AF_INET6 && dst->sa_family != AF_MPLS)) {
   58                 if (!ISSET(ifp->if_xflags, IFXF_MPLS))
   59                         return (ifp->if_output(ifp, m, dst, rt));
   60                 else
   61                         return (ifp->if_ll_output(ifp, m, dst, rt));
   62         }
   63 
   64         /* need to calculate checksums now if necessary */
   65         mpls_do_cksum(m);
   66 
   67         /* initialize sockaddr_mpls */
   68         bzero(&sa_mpls, sizeof(sa_mpls));
   69         smpls = &sa_mpls;
   70         smpls->smpls_family = AF_MPLS;
   71         smpls->smpls_len = sizeof(*smpls);
   72 
   73         ttl = mpls_getttl(m, dst->sa_family);
   74 
   75         rt_mpls = (struct rt_mpls *)rt->rt_llinfo;
   76         if (rt_mpls == NULL || (rt->rt_flags & RTF_MPLS) == 0) {
   77                 /* no MPLS information for this entry */
   78                 if (!ISSET(ifp->if_xflags, IFXF_MPLS)) {
   79 #ifdef MPLS_DEBUG
   80                         printf("MPLS_DEBUG: interface not mpls enabled\n");
   81 #endif
   82                         error = ENETUNREACH;
   83                         goto bad;
   84                 }
   85 
   86                 return (ifp->if_ll_output(ifp, m, dst, rt));
   87         }
   88 
   89         /* to be honest here only the push operation makes sense */
   90         switch (rt_mpls->mpls_operation) {
   91         case MPLS_OP_PUSH:
   92                 m = mpls_shim_push(m, rt_mpls);
   93                 break;
   94         case MPLS_OP_POP:
   95                 m = mpls_shim_pop(m);
   96                 break;
   97         case MPLS_OP_SWAP:
   98                 m = mpls_shim_swap(m, rt_mpls);
   99                 break;
  100         default:
  101                 error = EINVAL;
  102                 goto bad;
  103         }
  104 
  105         if (m == NULL) {
  106                 error = ENOBUFS;
  107                 goto bad;
  108         }
  109 
  110         /* refetch label */
  111         shim = mtod(m, struct shim_hdr *);
  112         /* mark first label with BOS flag */
  113         if (dst->sa_family != AF_MPLS)
  114                 shim->shim_label |= MPLS_BOS_MASK;
  115 
  116         /* write back TTL */
  117         shim->shim_label &= ~MPLS_TTL_MASK;
  118         shim->shim_label |= htonl(ttl);
  119 
  120 #ifdef MPLS_DEBUG
  121         printf("MPLS: sending on %s outshim %x outlabel %d\n",
  122             ifp->if_xname, ntohl(shim->shim_label),
  123             MPLS_LABEL_GET(rt_mpls->mpls_label));
  124 #endif
  125 
  126         /* Output iface is not MPLS-enabled */
  127         if (!ISSET(ifp->if_xflags, IFXF_MPLS)) {
  128 #ifdef MPLS_DEBUG
  129                 printf("MPLS_DEBUG: interface not mpls enabled\n");
  130 #endif
  131                 error = ENETUNREACH;
  132                 goto bad;
  133         }
  134 
  135         /* reset broadcast and multicast flags, this is a P2P tunnel */
  136         m->m_flags &= ~(M_BCAST | M_MCAST);
  137 
  138         smpls->smpls_label = shim->shim_label & MPLS_LABEL_MASK;
  139         error = ifp->if_ll_output(ifp, m, smplstosa(smpls), rt);
  140         return (error);
  141 bad:
  142         m_freem(m);
  143         return (error);
  144 }
  145 
  146 void
  147 mpls_do_cksum(struct mbuf *m)
  148 {
  149         struct ip *ip;
  150         u_int16_t hlen;
  151 
  152         in_proto_cksum_out(m, NULL);
  153 
  154         if (m->m_pkthdr.csum_flags & M_IPV4_CSUM_OUT) {
  155                 ip = mtod(m, struct ip *);
  156                 hlen = ip->ip_hl << 2;
  157                 ip->ip_sum = in_cksum(m, hlen);
  158                 m->m_pkthdr.csum_flags &= ~M_IPV4_CSUM_OUT;
  159         }
  160 }
  161 
  162 u_int8_t
  163 mpls_getttl(struct mbuf *m, sa_family_t af)
  164 {
  165         struct mbuf *n;
  166         int loc, off;
  167         u_int8_t ttl = mpls_defttl;
  168 
  169         /* If the AF is MPLS then inherit the TTL from the present label. */
  170         if (af == AF_MPLS)
  171                 loc = 3;
  172         else {
  173                 switch (*mtod(m, uint8_t *) >> 4) {
  174                 case 4:
  175                         if (!mpls_mapttl_ip)
  176                                 return (ttl);
  177 
  178                         loc = offsetof(struct ip, ip_ttl);
  179                         break;
  180 #ifdef INET6
  181                 case 6:
  182                         if (!mpls_mapttl_ip6)
  183                                 return (ttl);
  184 
  185                         loc = offsetof(struct ip6_hdr, ip6_hlim);
  186                         break;
  187 #endif
  188                 default:
  189                         return (ttl);
  190                 }
  191         }
  192 
  193         n = m_getptr(m, loc, &off);
  194         if (n == NULL)
  195                 return (ttl);
  196 
  197         ttl = *(mtod(n, uint8_t *) + off);
  198 
  199         return (ttl);
  200 }

Cache object: dbc1a2cd617550469dbdeb6027cdb9df


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.