Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet6/send.c
Show First 20 Lines • Show All 111 Lines • ▼ Show 20 Lines | |||||
static int | static int | ||||
send_output(struct mbuf *m, struct ifnet *ifp, int direction) | send_output(struct mbuf *m, struct ifnet *ifp, int direction) | ||||
{ | { | ||||
struct ip6_hdr *ip6; | struct ip6_hdr *ip6; | ||||
struct sockaddr_in6 dst; | struct sockaddr_in6 dst; | ||||
struct icmp6_hdr *icmp6; | struct icmp6_hdr *icmp6; | ||||
struct epoch_tracker et; | struct epoch_tracker et; | ||||
int icmp6len; | int icmp6len; | ||||
int error; | |||||
/* | /* | ||||
* Receive incoming (SeND-protected) or outgoing traffic | * Receive incoming (SeND-protected) or outgoing traffic | ||||
* (SeND-validated) from the SeND user space application. | * (SeND-validated) from the SeND user space application. | ||||
*/ | */ | ||||
switch (direction) { | switch (direction) { | ||||
case SND_IN: | case SND_IN: | ||||
Show All 10 Lines | case SND_IN: | ||||
if (m->m_flags & M_PKTHDR) | if (m->m_flags & M_PKTHDR) | ||||
icmp6len = m->m_pkthdr.len - sizeof(struct ip6_hdr); | icmp6len = m->m_pkthdr.len - sizeof(struct ip6_hdr); | ||||
else | else | ||||
panic("Doh! not the first mbuf."); | panic("Doh! not the first mbuf."); | ||||
ip6 = mtod(m, struct ip6_hdr *); | ip6 = mtod(m, struct ip6_hdr *); | ||||
icmp6 = (struct icmp6_hdr *)(ip6 + 1); | icmp6 = (struct icmp6_hdr *)(ip6 + 1); | ||||
error = 0; | |||||
/* | /* | ||||
* Output the packet as icmp6.c:icpm6_input() would do. | * Output the packet as icmp6.c:icpm6_input() would do. | ||||
* The mbuf is always consumed, so we do not have to | * The mbuf is always consumed, so we do not have to | ||||
* care about that. | * care about that. | ||||
*/ | */ | ||||
NET_EPOCH_ENTER(et); | |||||
switch (icmp6->icmp6_type) { | switch (icmp6->icmp6_type) { | ||||
donner: I assume, the other functions do not need epoch at the moment.
If they ever need it sometimes… | |||||
case ND_NEIGHBOR_SOLICIT: | case ND_NEIGHBOR_SOLICIT: | ||||
NET_EPOCH_ENTER(et); | |||||
nd6_ns_input(m, sizeof(struct ip6_hdr), icmp6len); | nd6_ns_input(m, sizeof(struct ip6_hdr), icmp6len); | ||||
NET_EPOCH_EXIT(et); | |||||
break; | break; | ||||
case ND_NEIGHBOR_ADVERT: | case ND_NEIGHBOR_ADVERT: | ||||
nd6_na_input(m, sizeof(struct ip6_hdr), icmp6len); | nd6_na_input(m, sizeof(struct ip6_hdr), icmp6len); | ||||
break; | break; | ||||
case ND_REDIRECT: | case ND_REDIRECT: | ||||
icmp6_redirect_input(m, sizeof(struct ip6_hdr)); | icmp6_redirect_input(m, sizeof(struct ip6_hdr)); | ||||
break; | break; | ||||
case ND_ROUTER_SOLICIT: | case ND_ROUTER_SOLICIT: | ||||
nd6_rs_input(m, sizeof(struct ip6_hdr), icmp6len); | nd6_rs_input(m, sizeof(struct ip6_hdr), icmp6len); | ||||
break; | break; | ||||
case ND_ROUTER_ADVERT: | case ND_ROUTER_ADVERT: | ||||
nd6_ra_input(m, sizeof(struct ip6_hdr), icmp6len); | nd6_ra_input(m, sizeof(struct ip6_hdr), icmp6len); | ||||
break; | break; | ||||
default: | default: | ||||
m_freem(m); | m_freem(m); | ||||
return (ENOSYS); | error = ENOSYS; | ||||
} | } | ||||
return (0); | NET_EPOCH_EXIT(et); | ||||
return (error); | |||||
case SND_OUT: | case SND_OUT: | ||||
if (m->m_len < sizeof(struct ip6_hdr)) { | if (m->m_len < sizeof(struct ip6_hdr)) { | ||||
m = m_pullup(m, sizeof(struct ip6_hdr)); | m = m_pullup(m, sizeof(struct ip6_hdr)); | ||||
if (!m) | if (!m) | ||||
return (ENOBUFS); | return (ENOBUFS); | ||||
} | } | ||||
ip6 = mtod(m, struct ip6_hdr *); | ip6 = mtod(m, struct ip6_hdr *); | ||||
if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) | if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) | ||||
Show All 10 Lines | case SND_OUT: | ||||
/* | /* | ||||
* Output the packet as nd6.c:nd6_output_lle() would do. | * Output the packet as nd6.c:nd6_output_lle() would do. | ||||
* The mbuf is always consumed, so we do not have to care | * The mbuf is always consumed, so we do not have to care | ||||
* about that. | * about that. | ||||
* XXX-BZ as we added data, what about fragmenting, | * XXX-BZ as we added data, what about fragmenting, | ||||
* if now needed? | * if now needed? | ||||
*/ | */ | ||||
int error; | |||||
error = ((*ifp->if_output)(ifp, m, (struct sockaddr *)&dst, | error = ((*ifp->if_output)(ifp, m, (struct sockaddr *)&dst, | ||||
NULL)); | NULL)); | ||||
if (error) | if (error) | ||||
error = ENOENT; | error = ENOENT; | ||||
return (error); | return (error); | ||||
default: | default: | ||||
panic("%s: direction %d neither SND_IN nor SND_OUT.", | panic("%s: direction %d neither SND_IN nor SND_OUT.", | ||||
▲ Show 20 Lines • Show All 169 Lines • Show Last 20 Lines |
I assume, the other functions do not need epoch at the moment.
If they ever need it sometimes in the future, the scope can be extended to the whole switch.