Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet6/ip6_output.c
Show First 20 Lines • Show All 59 Lines • ▼ Show 20 Lines | |||||
* @(#)ip_output.c 8.3 (Berkeley) 1/21/94 | * @(#)ip_output.c 8.3 (Berkeley) 1/21/94 | ||||
*/ | */ | ||||
#include <sys/cdefs.h> | #include <sys/cdefs.h> | ||||
__FBSDID("$FreeBSD$"); | __FBSDID("$FreeBSD$"); | ||||
#include "opt_inet.h" | #include "opt_inet.h" | ||||
#include "opt_inet6.h" | #include "opt_inet6.h" | ||||
#include "opt_ratelimit.h" | |||||
#include "opt_ipsec.h" | #include "opt_ipsec.h" | ||||
#include "opt_sctp.h" | #include "opt_sctp.h" | ||||
#include "opt_route.h" | #include "opt_route.h" | ||||
#include "opt_rss.h" | #include "opt_rss.h" | ||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/kernel.h> | #include <sys/kernel.h> | ||||
#include <sys/malloc.h> | #include <sys/malloc.h> | ||||
▲ Show 20 Lines • Show All 853 Lines • ▼ Show 20 Lines | if (dontfrag && tlen > IN6_LINKMTU(ifp) && !tso) { /* case 2-b */ | ||||
* Even if the DONTFRAG option is specified, we cannot send the | * Even if the DONTFRAG option is specified, we cannot send the | ||||
* packet when the data length is larger than the MTU of the | * packet when the data length is larger than the MTU of the | ||||
* outgoing interface. | * outgoing interface. | ||||
* Notify the error by sending IPV6_PATHMTU ancillary data if | * Notify the error by sending IPV6_PATHMTU ancillary data if | ||||
* application wanted to know the MTU value. Also return an | * application wanted to know the MTU value. Also return an | ||||
* error code (this is not described in the API spec). | * error code (this is not described in the API spec). | ||||
*/ | */ | ||||
if (inp != NULL) | if (inp != NULL) | ||||
ip6_notify_pmtu(inp, &dst_sa, (u_int32_t)mtu); | ip6_notify_pmtu(inp, &dst_sa, (u_int32_t)mtu); | ||||
julian: Why is this duplicated for ipv6 and ipv4? can it not be made common? | |||||
Done Inline ActionsWill be fixed. Please wait for updated patch. Thank you! hselasky: Will be fixed. Please wait for updated patch. Thank you! | |||||
error = EMSGSIZE; | error = EMSGSIZE; | ||||
goto bad; | goto bad; | ||||
} | } | ||||
/* | /* | ||||
* transmit packet without fragmentation | * transmit packet without fragmentation | ||||
*/ | */ | ||||
if (dontfrag || (!alwaysfrag && tlen <= mtu)) { /* case 1-a and 2-a */ | if (dontfrag || (!alwaysfrag && tlen <= mtu)) { /* case 1-a and 2-a */ | ||||
struct in6_ifaddr *ia6; | struct in6_ifaddr *ia6; | ||||
ip6 = mtod(m, struct ip6_hdr *); | ip6 = mtod(m, struct ip6_hdr *); | ||||
ia6 = in6_ifawithifp(ifp, &ip6->ip6_src); | ia6 = in6_ifawithifp(ifp, &ip6->ip6_src); | ||||
if (ia6) { | if (ia6) { | ||||
/* Record statistics for this interface address. */ | /* Record statistics for this interface address. */ | ||||
counter_u64_add(ia6->ia_ifa.ifa_opackets, 1); | counter_u64_add(ia6->ia_ifa.ifa_opackets, 1); | ||||
counter_u64_add(ia6->ia_ifa.ifa_obytes, | counter_u64_add(ia6->ia_ifa.ifa_obytes, | ||||
m->m_pkthdr.len); | m->m_pkthdr.len); | ||||
ifa_free(&ia6->ia_ifa); | ifa_free(&ia6->ia_ifa); | ||||
} | } | ||||
#ifdef RATELIMIT | |||||
retry_if_output_0: | |||||
if (inp->inp_flags2 & INP_RATE_LIMIT_CHANGED) | |||||
in_pcboutput_txrtlmt(inp, ifp, m); | |||||
/* stamp send tag on mbuf */ | |||||
m->m_pkthdr.snd_tag = inp->inp_snd_tag; | |||||
#endif | |||||
error = nd6_output_ifp(ifp, origifp, m, dst, | error = nd6_output_ifp(ifp, origifp, m, dst, | ||||
(struct route *)ro); | (struct route *)ro); | ||||
#ifdef RATELIMIT | |||||
if (error == EAGAIN) { | |||||
/* route changed, mbuf was not freed */ | |||||
error = in_pcboutput_eagain(inp, m); | |||||
if (error == EAGAIN) | |||||
goto retry_if_output_0; | |||||
} | |||||
#endif | |||||
goto done; | goto done; | ||||
} | } | ||||
/* | /* | ||||
* try to fragment the packet. case 1-b and 3 | * try to fragment the packet. case 1-b and 3 | ||||
*/ | */ | ||||
if (mtu < IPV6_MMTU) { | if (mtu < IPV6_MMTU) { | ||||
/* path MTU cannot be less than IPV6_MMTU */ | /* path MTU cannot be less than IPV6_MMTU */ | ||||
▲ Show 20 Lines • Show All 82 Lines • ▼ Show 20 Lines | for (m0 = m; m; m = m0) { | ||||
m->m_nextpkt = 0; | m->m_nextpkt = 0; | ||||
if (error == 0) { | if (error == 0) { | ||||
/* Record statistics for this interface address. */ | /* Record statistics for this interface address. */ | ||||
if (ia) { | if (ia) { | ||||
counter_u64_add(ia->ia_ifa.ifa_opackets, 1); | counter_u64_add(ia->ia_ifa.ifa_opackets, 1); | ||||
counter_u64_add(ia->ia_ifa.ifa_obytes, | counter_u64_add(ia->ia_ifa.ifa_obytes, | ||||
m->m_pkthdr.len); | m->m_pkthdr.len); | ||||
} | } | ||||
#ifdef RATELIMIT | |||||
retry_if_output_1: | |||||
if (ifp->if_capabilities & IFCAP_TXRTLMT) | |||||
in_pcboutput_txrtlmt(inp, ifp, m); | |||||
/* stamp send tag on mbuf */ | |||||
m->m_pkthdr.snd_tag = inp->inp_snd_tag; | |||||
#endif | |||||
error = nd6_output_ifp(ifp, origifp, m, dst, | error = nd6_output_ifp(ifp, origifp, m, dst, | ||||
(struct route *)ro); | (struct route *)ro); | ||||
#ifdef RATELIMIT | |||||
if (error == EAGAIN) { | |||||
/* route changed, mbuf was not freed */ | |||||
error = in_pcboutput_eagain(inp, m); | |||||
if (error == EAGAIN) | |||||
goto retry_if_output_1; | |||||
} | |||||
#endif | |||||
} else | } else | ||||
m_freem(m); | m_freem(m); | ||||
} | } | ||||
if (error == 0) | if (error == 0) | ||||
IP6STAT_INC(ip6s_fragmented); | IP6STAT_INC(ip6s_fragmented); | ||||
done: | done: | ||||
▲ Show 20 Lines • Show All 368 Lines • ▼ Show 20 Lines | if (sopt->sopt_level == SOL_SOCKET && | ||||
INP_WUNLOCK(in6p); | INP_WUNLOCK(in6p); | ||||
error = 0; | error = 0; | ||||
break; | break; | ||||
case SO_SETFIB: | case SO_SETFIB: | ||||
INP_WLOCK(in6p); | INP_WLOCK(in6p); | ||||
in6p->inp_inc.inc_fibnum = so->so_fibnum; | in6p->inp_inc.inc_fibnum = so->so_fibnum; | ||||
INP_WUNLOCK(in6p); | INP_WUNLOCK(in6p); | ||||
error = 0; | error = 0; | ||||
break; | |||||
case SO_MAX_PACING_RATE: | |||||
#ifdef RATELIMIT | |||||
INP_WLOCK(in6p); | |||||
in6p->inp_flags2 |= INP_RATE_LIMIT_CHANGED; | |||||
INP_WUNLOCK(in6p); | |||||
error = 0; | |||||
#else | |||||
error = EOPNOTSUPP; | |||||
#endif | |||||
break; | break; | ||||
default: | default: | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
} else { /* level == IPPROTO_IPV6 */ | } else { /* level == IPPROTO_IPV6 */ | ||||
switch (op) { | switch (op) { | ||||
▲ Show 20 Lines • Show All 1,648 Lines • Show Last 20 Lines |
Why is this duplicated for ipv6 and ipv4? can it not be made common?