/* * Start output on the mpe interface. */ void mpestart(struct ifnet *ifp) { struct mbuf *m; struct sockaddr *sa = (struct sockaddr *)&mpedst; int s; sa_family_t af; struct rtentry *rt; for (;;) { s = splnet(); IFQ_DEQUEUE(&ifp->if_snd, m); splx(s); if (m == NULL) return; af = *mtod(m, sa_family_t *); m_adj(m, sizeof(af)); switch (af) { case AF_INET: bzero(sa, sizeof(struct sockaddr_in)); satosin(sa)->sin_family = af; satosin(sa)->sin_len = sizeof(struct sockaddr_in); bcopy(mtod(m, caddr_t), &satosin(sa)->sin_addr, sizeof(in_addr_t)); m_adj(m, sizeof(in_addr_t)); break; default: m_freem(m); continue; } 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 */ m->m_data += sizeof(struct shim_hdr); m->m_len -= sizeof(struct shim_hdr); m->m_pkthdr.len -= sizeof(struct shim_hdr); bpf_mtap_af(ifp->if_bpf, af, m, BPF_DIRECTION_OUT); m->m_data -= sizeof(struct shim_hdr); m->m_len += sizeof(struct shim_hdr); 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); } }
static void mpls_forward(struct mbuf *m) { struct sockaddr_mpls *smpls; struct mpls *mpls; struct route *cache_rt = &mplsforward_rt[mycpuid]; mpls_label_t label; struct ifnet *ifp; struct sockaddr *dst; int error; KASSERT(m->m_len >= sizeof(struct mpls), ("mpls_forward: mpls header not in one mbuf")); mpls = mtod(m, struct mpls *); label = MPLS_LABEL(ntohl(mpls->mpls_shim)); smpls = (struct sockaddr_mpls *) &cache_rt->ro_dst; if (cache_rt->ro_rt == NULL || smpls->smpls_label != label) { if (cache_rt->ro_rt != NULL) { RTFREE(cache_rt->ro_rt); cache_rt->ro_rt = NULL; } smpls->smpls_family = AF_MPLS; smpls->smpls_len = sizeof(struct sockaddr_mpls); smpls->smpls_label = htonl(label); rtalloc(cache_rt); if (cache_rt->ro_rt == NULL) { /* route not found */ return; } } ifp = cache_rt->ro_rt->rt_ifp; dst = cache_rt->ro_rt->rt_gateway; error = mpls_output(m, cache_rt->ro_rt); if (error) goto bad; error = (*ifp->if_output)(ifp, m, dst, cache_rt->ro_rt); if (error) goto bad; mplsstat.mplss_forwarded++; return; bad: m_freem(m); }