Example #1
0
/*
 * 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);
	}
}
Example #2
0
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);
}