Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet/ip_output.c
Show First 20 Lines • Show All 79 Lines • ▼ Show 20 Lines | |||||
#include <netinet/in_fib.h> | #include <netinet/in_fib.h> | ||||
#include <netinet/in_pcb.h> | #include <netinet/in_pcb.h> | ||||
#include <netinet/in_rss.h> | #include <netinet/in_rss.h> | ||||
#include <netinet/in_var.h> | #include <netinet/in_var.h> | ||||
#include <netinet/ip_var.h> | #include <netinet/ip_var.h> | ||||
#include <netinet/ip_options.h> | #include <netinet/ip_options.h> | ||||
#include <netinet/ip_mroute.h> | #include <netinet/ip_mroute.h> | ||||
#include <netinet/tcp_var.h> | |||||
#include <netinet/udp.h> | #include <netinet/udp.h> | ||||
#include <netinet/udp_var.h> | #include <netinet/udp_var.h> | ||||
#if defined(SCTP) || defined(SCTP_SUPPORT) | #if defined(SCTP) || defined(SCTP_SUPPORT) | ||||
#include <netinet/sctp.h> | #include <netinet/sctp.h> | ||||
#include <netinet/sctp_crc32.h> | #include <netinet/sctp_crc32.h> | ||||
#endif | #endif | ||||
#include <netipsec/ipsec_support.h> | #include <netipsec/ipsec_support.h> | ||||
#include <machine/in_cksum.h> | #include <machine/in_cksum.h> | ||||
#include <security/mac/mac_framework.h> | #include <security/mac/mac_framework.h> | ||||
#ifdef MBUF_STRESS_TEST | #ifdef MBUF_STRESS_TEST | ||||
static int mbuf_frag_size = 0; | static int mbuf_frag_size = 0; | ||||
SYSCTL_INT(_net_inet_ip, OID_AUTO, mbuf_frag_size, CTLFLAG_RW, | SYSCTL_INT(_net_inet_ip, OID_AUTO, mbuf_frag_size, CTLFLAG_RW, | ||||
&mbuf_frag_size, 0, "Fragment outgoing mbufs to this size"); | &mbuf_frag_size, 0, "Fragment outgoing mbufs to this size"); | ||||
#endif | #endif | ||||
VNET_DEFINE(int, rfc1191); | |||||
SYSCTL_INT(_net_inet_ip, 0, rfc1191, CTLFLAG_VNET | CTLFLAG_RW, | |||||
&VNET_NAME(rfc1191), 0, "Enable RFC1191 PMTU support"); | |||||
static void ip_mloopback(struct ifnet *, const struct mbuf *, int); | static void ip_mloopback(struct ifnet *, const struct mbuf *, int); | ||||
extern int in_mcast_loop; | extern int in_mcast_loop; | ||||
extern struct protosw inetsw[]; | extern struct protosw inetsw[]; | ||||
static inline int | static inline int | ||||
ip_output_pfil(struct mbuf **mp, struct ifnet *ifp, int flags, | ip_output_pfil(struct mbuf **mp, struct ifnet *ifp, int flags, | ||||
struct inpcb *inp, struct sockaddr_in *dst, int *fibnum, int *error) | struct inpcb *inp, struct sockaddr_in *dst, int *fibnum, int *error) | ||||
▲ Show 20 Lines • Show All 184 Lines • ▼ Show 20 Lines | rt_update_ro_flags(struct route *ro) | ||||
ro->ro_flags &= ~ (RT_REJECT|RT_BLACKHOLE|RT_HAS_GW); | ro->ro_flags &= ~ (RT_REJECT|RT_BLACKHOLE|RT_HAS_GW); | ||||
ro->ro_flags |= (nh_flags & NHF_REJECT) ? RT_REJECT : 0; | ro->ro_flags |= (nh_flags & NHF_REJECT) ? RT_REJECT : 0; | ||||
ro->ro_flags |= (nh_flags & NHF_BLACKHOLE) ? RT_BLACKHOLE : 0; | ro->ro_flags |= (nh_flags & NHF_BLACKHOLE) ? RT_BLACKHOLE : 0; | ||||
ro->ro_flags |= (nh_flags & NHF_GATEWAY) ? RT_HAS_GW : 0; | ro->ro_flags |= (nh_flags & NHF_GATEWAY) ? RT_HAS_GW : 0; | ||||
} | } | ||||
/* | /* | ||||
* Calculates IPv4 path MTU for @dst based on the hostcache data and a fallback | |||||
* nexthop MTU value @nh_mtu. | |||||
* | |||||
* Note that @nh_mtu is a valid fall-back MTU if there is no PMTU entry in the | |||||
* hostcache. It does not need to necessarily come from nh_object, as is the | |||||
* case when this function is called from ip_output() for a broadcast | |||||
* destination. | |||||
* | |||||
* Returns the calculated MTU. | |||||
*/ | |||||
static uint32_t | |||||
ip_calcpmtu(const struct in_addr dst, uint32_t nh_mtu, u_int proto) | |||||
{ | |||||
uint32_t mtu = 0; | |||||
struct in_conninfo inc; | |||||
bzero(&inc, sizeof(inc)); | |||||
inc.inc_faddr = dst; | |||||
/* TCP is known to react to pmtu changes so skip hc, | |||||
* XXX: Either add list of known good protocols or an inpcb flag filled | |||||
* by the PMTU aware protocol. | |||||
*/ | |||||
if (proto != IPPROTO_TCP) | |||||
mtu = tcp_hc_getmtu(&inc); | |||||
if (mtu) | |||||
mtu = min(mtu, nh_mtu); | |||||
else | |||||
mtu = nh_mtu; | |||||
/* XXX: below is an extremely unlikely case, because it is a minimal | |||||
* unfragmented packet size (RFC 791). | |||||
*/ | |||||
if (__predict_false(mtu < IP_MMTU)) | |||||
mtu = IP_MMTU; | |||||
return mtu; | |||||
} | |||||
/* | |||||
* IP output. The packet in mbuf chain m contains a skeletal IP | * IP output. The packet in mbuf chain m contains a skeletal IP | ||||
* header (with len, off, ttl, proto, tos, src, dst). | * header (with len, off, ttl, proto, tos, src, dst). | ||||
* The mbuf chain containing the packet will be freed. | * The mbuf chain containing the packet will be freed. | ||||
* The mbuf opt, if present, will not be freed. | * The mbuf opt, if present, will not be freed. | ||||
* If route ro is present and has ro_rt initialized, route lookup would be | * If route ro is present and has ro_rt initialized, route lookup would be | ||||
* skipped and ro->ro_rt would be used. If ro is present but ro->ro_rt is NULL, | * skipped and ro->ro_rt would be used. If ro is present but ro->ro_rt is NULL, | ||||
* then result of route lookup is stored in ro->ro_rt. | * then result of route lookup is stored in ro->ro_rt. | ||||
* | * | ||||
* In the IP forwarding case, the packet will arrive with options already | * In the IP forwarding case, the packet will arrive with options already | ||||
* inserted, so must have a NULL opt pointer. | * inserted, so must have a NULL opt pointer. | ||||
*/ | */ | ||||
int | int | ||||
ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags, | ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags, | ||||
struct ip_moptions *imo, struct inpcb *inp) | struct ip_moptions *imo, struct inpcb *inp) | ||||
{ | { | ||||
MROUTER_RLOCK_TRACKER; | MROUTER_RLOCK_TRACKER; | ||||
struct rm_priotracker in_ifa_tracker; | struct rm_priotracker in_ifa_tracker; | ||||
struct ip *ip; | struct ip *ip; | ||||
struct ifnet *ifp = NULL; /* keep compiler happy */ | struct ifnet *ifp = NULL; /* keep compiler happy */ | ||||
struct mbuf *m0; | struct mbuf *m0; | ||||
int hlen = sizeof (struct ip); | int hlen = sizeof (struct ip); | ||||
int mtu = 0; | |||||
int error = 0; | int error = 0; | ||||
int vlan_pcp = -1; | int vlan_pcp = -1; | ||||
struct sockaddr_in *dst, sin; | struct sockaddr_in *dst, sin; | ||||
const struct sockaddr_in *gw; | const struct sockaddr_in *gw; | ||||
struct in_ifaddr *ia = NULL; | struct in_ifaddr *ia = NULL; | ||||
struct in_addr src; | struct in_addr src; | ||||
int isbroadcast; | int isbroadcast; | ||||
uint16_t ip_len, ip_off; | uint16_t ip_len, ip_off; | ||||
uint32_t fibnum; | uint32_t fibnum, mtu = 0; | ||||
#if defined(IPSEC) || defined(IPSEC_SUPPORT) | #if defined(IPSEC) || defined(IPSEC_SUPPORT) | ||||
int no_route_but_check_spd = 0; | int no_route_but_check_spd = 0; | ||||
#endif | #endif | ||||
M_ASSERTPKTHDR(m); | M_ASSERTPKTHDR(m); | ||||
NET_EPOCH_ASSERT(); | NET_EPOCH_ASSERT(); | ||||
if (inp != NULL) { | if (inp != NULL) { | ||||
▲ Show 20 Lines • Show All 198 Lines • ▼ Show 20 Lines | #endif | ||||
ia = ifatoia(nh->nh_ifa); | ia = ifatoia(nh->nh_ifa); | ||||
src = IA_SIN(ia)->sin_addr; | src = IA_SIN(ia)->sin_addr; | ||||
isbroadcast = (((nh->nh_flags & (NHF_HOST | NHF_BROADCAST)) == | isbroadcast = (((nh->nh_flags & (NHF_HOST | NHF_BROADCAST)) == | ||||
(NHF_HOST | NHF_BROADCAST)) || | (NHF_HOST | NHF_BROADCAST)) || | ||||
((ifp->if_flags & IFF_BROADCAST) && | ((ifp->if_flags & IFF_BROADCAST) && | ||||
in_ifaddr_broadcast(dst->sin_addr, ia))); | in_ifaddr_broadcast(dst->sin_addr, ia))); | ||||
} | } | ||||
/* Determine the path MTU. */ | |||||
if (V_rfc1191) | |||||
mtu = ip_calcpmtu(ip->ip_dst, mtu, ip->ip_p); | |||||
/* Catch a possible divide by zero later. */ | /* Catch a possible divide by zero later. */ | ||||
KASSERT(mtu > 0, ("%s: mtu %d <= 0, ro=%p (nh_flags=0x%08x) ifp=%p", | KASSERT(mtu > 0, ("%s: mtu %d <= 0, ro=%p (nh_flags=0x%08x) ifp=%p", | ||||
__func__, mtu, ro, | __func__, mtu, ro, | ||||
(ro != NULL && ro->ro_nh != NULL) ? ro->ro_nh->nh_flags : 0, ifp)); | (ro != NULL && ro->ro_nh != NULL) ? ro->ro_nh->nh_flags : 0, ifp)); | ||||
if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) { | if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) { | ||||
m->m_flags |= M_MCAST; | m->m_flags |= M_MCAST; | ||||
/* | /* | ||||
▲ Show 20 Lines • Show All 1,073 Lines • Show Last 20 Lines |