Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F115710877
D44204.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
8 KB
Referenced Files
None
Subscribers
None
D44204.diff
View Options
diff --git a/sys/netinet6/ip6_output.c b/sys/netinet6/ip6_output.c
--- a/sys/netinet6/ip6_output.c
+++ b/sys/netinet6/ip6_output.c
@@ -159,14 +159,12 @@
*/
#define MAKE_EXTHDR(hp, mp, _ol) \
do { \
- if (hp) { \
- struct ip6_ext *eh = (struct ip6_ext *)(hp); \
- error = ip6_copyexthdr((mp), (caddr_t)(hp), \
- ((eh)->ip6e_len + 1) << 3); \
- if (error) \
- goto freehdrs; \
- (_ol) += (*(mp))->m_len; \
- } \
+ struct ip6_ext *eh = (struct ip6_ext *)(hp); \
+ error = ip6_copyexthdr((mp), (caddr_t)(hp), \
+ ((eh)->ip6e_len + 1) << 3); \
+ if (error) \
+ goto freehdrs; \
+ (_ol) += (*(mp))->m_len; \
} while (/*CONSTCOND*/ 0)
/*
@@ -431,6 +429,7 @@
uint32_t fibnum;
struct m_tag *fwd_tag = NULL;
uint32_t id;
+ uint32_t optvalid;
NET_EPOCH_ASSERT();
@@ -491,14 +490,17 @@
* Keep the length of the unfragmentable part for fragmentation.
*/
bzero(&exthdrs, sizeof(exthdrs));
- optlen = 0;
+ optlen = optvalid = 0;
unfragpartlen = sizeof(struct ip6_hdr);
if (opt) {
+ optvalid = opt->ip6po_valid;
+
/* Hop-by-Hop options header. */
- MAKE_EXTHDR(opt->ip6po_hbh, &exthdrs.ip6e_hbh, optlen);
+ if ((optvalid & IP6PO_VALID_HBH) != 0)
+ MAKE_EXTHDR(opt->ip6po_hbh, &exthdrs.ip6e_hbh, optlen);
/* Destination options header (1st part). */
- if (opt->ip6po_rthdr) {
+ if ((optvalid & IP6PO_VALID_RHINFO) != 0) {
#ifndef RTHDR_SUPPORT_IMPLEMENTED
/*
* If there is a routing header, discard the packet
@@ -524,11 +526,13 @@
* options, which might automatically be inserted in
* the kernel.
*/
- MAKE_EXTHDR(opt->ip6po_dest1, &exthdrs.ip6e_dest1,
- optlen);
+ if ((optvalid & IP6PO_VALID_DEST1) != 0)
+ MAKE_EXTHDR(opt->ip6po_dest1, &exthdrs.ip6e_dest1,
+ optlen);
}
/* Routing header. */
- MAKE_EXTHDR(opt->ip6po_rthdr, &exthdrs.ip6e_rthdr, optlen);
+ if ((optvalid & IP6PO_VALID_RHINFO) != 0)
+ MAKE_EXTHDR(opt->ip6po_rthdr, &exthdrs.ip6e_rthdr, optlen);
unfragpartlen += optlen;
@@ -538,7 +542,8 @@
*/
/* Destination options header (2nd part). */
- MAKE_EXTHDR(opt->ip6po_dest2, &exthdrs.ip6e_dest2, optlen);
+ if ((optvalid & IP6PO_VALID_DEST2) != 0)
+ MAKE_EXTHDR(opt->ip6po_dest2, &exthdrs.ip6e_dest2, optlen);
}
/*
@@ -627,7 +632,7 @@
/* Route packet. */
ro_pmtu = ro;
- if (opt && opt->ip6po_rthdr)
+ if ((optvalid & IP6PO_VALID_RHINFO) != 0)
ro = &opt->ip6po_route;
if (ro != NULL)
dst = (struct sockaddr_in6 *)&ro->ro_dst;
@@ -641,7 +646,7 @@
* Do not override if a non-zero value is already set.
* We check the diffserv field and the ECN field separately.
*/
- if (opt && opt->ip6po_tclass >= 0) {
+ if ((optvalid & IP6PO_VALID_TC) != 0){
int mask = 0;
if (IPV6_DSCP(ip6) == 0)
@@ -653,7 +658,7 @@
}
/* Fill in or override the hop limit field, if necessary. */
- if (opt && opt->ip6po_hlim != -1)
+ if ((optvalid & IP6PO_VALID_HLIM) != 0)
ip6->ip6_hlim = opt->ip6po_hlim & 0xff;
else if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
if (im6o != NULL)
@@ -855,7 +860,7 @@
/* All scope ID checks are successful. */
if (nh && !IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
- if (opt && opt->ip6po_nextroute.ro_nh) {
+ if ((optvalid & IP6PO_VALID_NHINFO) != 0) {
/*
* The nexthop is explicitly specified by the
* application. We assume the next hop is an IPv6
@@ -2648,10 +2653,14 @@
free(pktopt->ip6po_pktinfo, M_IP6OPT);
pktopt->ip6po_pktinfo = NULL;
}
- if (optname == -1 || optname == IPV6_HOPLIMIT)
+ if (optname == -1 || optname == IPV6_HOPLIMIT) {
pktopt->ip6po_hlim = -1;
- if (optname == -1 || optname == IPV6_TCLASS)
+ pktopt->ip6po_valid &= ~IP6PO_VALID_HLIM;
+ }
+ if (optname == -1 || optname == IPV6_TCLASS) {
pktopt->ip6po_tclass = -1;
+ pktopt->ip6po_valid &= ~IP6PO_VALID_TC;
+ }
if (optname == -1 || optname == IPV6_NEXTHOP) {
if (pktopt->ip6po_nextroute.ro_nh) {
NH_FREE(pktopt->ip6po_nextroute.ro_nh);
@@ -2660,16 +2669,19 @@
if (pktopt->ip6po_nexthop)
free(pktopt->ip6po_nexthop, M_IP6OPT);
pktopt->ip6po_nexthop = NULL;
+ pktopt->ip6po_valid &= ~IP6PO_VALID_NHINFO;
}
if (optname == -1 || optname == IPV6_HOPOPTS) {
if (pktopt->ip6po_hbh)
free(pktopt->ip6po_hbh, M_IP6OPT);
pktopt->ip6po_hbh = NULL;
+ pktopt->ip6po_valid &= ~IP6PO_VALID_HBH;
}
if (optname == -1 || optname == IPV6_RTHDRDSTOPTS) {
if (pktopt->ip6po_dest1)
free(pktopt->ip6po_dest1, M_IP6OPT);
pktopt->ip6po_dest1 = NULL;
+ pktopt->ip6po_valid &= ~IP6PO_VALID_DEST1;
}
if (optname == -1 || optname == IPV6_RTHDR) {
if (pktopt->ip6po_rhinfo.ip6po_rhi_rthdr)
@@ -2679,11 +2691,13 @@
NH_FREE(pktopt->ip6po_route.ro_nh);
pktopt->ip6po_route.ro_nh = NULL;
}
+ pktopt->ip6po_valid &= ~IP6PO_VALID_RHINFO;
}
if (optname == -1 || optname == IPV6_DSTOPTS) {
if (pktopt->ip6po_dest2)
free(pktopt->ip6po_dest2, M_IP6OPT);
pktopt->ip6po_dest2 = NULL;
+ pktopt->ip6po_valid &= ~IP6PO_VALID_DEST2;
}
}
@@ -2730,6 +2744,7 @@
PKTOPT_EXTHDRCPY(ip6po_dest1);
PKTOPT_EXTHDRCPY(ip6po_dest2);
PKTOPT_EXTHDRCPY(ip6po_rthdr); /* not copy the cached route */
+ dst->ip6po_valid = src->ip6po_valid;
return (0);
bad:
@@ -2959,6 +2974,7 @@
return (ENOBUFS);
}
bcopy(pktinfo, opt->ip6po_pktinfo, sizeof(*pktinfo));
+ opt->ip6po_valid |= IP6PO_VALID_PKTINFO;
break;
}
@@ -2981,6 +2997,7 @@
return (EINVAL);
opt->ip6po_hlim = *hlimp;
+ opt->ip6po_valid |= IP6PO_VALID_HLIM;
break;
}
@@ -2995,6 +3012,7 @@
return (EINVAL);
opt->ip6po_tclass = tclass;
+ opt->ip6po_valid |= IP6PO_VALID_TC;
break;
}
@@ -3045,6 +3063,7 @@
if (opt->ip6po_nexthop == NULL)
return (ENOBUFS);
bcopy(buf, opt->ip6po_nexthop, *buf);
+ opt->ip6po_valid |= IP6PO_VALID_NHINFO;
break;
case IPV6_2292HOPOPTS:
@@ -3083,6 +3102,7 @@
if (opt->ip6po_hbh == NULL)
return (ENOBUFS);
bcopy(hbh, opt->ip6po_hbh, hbhlen);
+ opt->ip6po_valid |= IP6PO_VALID_HBH;
break;
}
@@ -3150,6 +3170,10 @@
if (*newdest == NULL)
return (ENOBUFS);
bcopy(dest, *newdest, destlen);
+ if (newdest == &opt->ip6po_dest1)
+ opt->ip6po_valid |= IP6PO_VALID_DEST1;
+ else
+ opt->ip6po_valid |= IP6PO_VALID_DEST2;
break;
}
@@ -3192,6 +3216,7 @@
if (opt->ip6po_rthdr == NULL)
return (ENOBUFS);
bcopy(rth, opt->ip6po_rthdr, rthlen);
+ opt->ip6po_valid |= IP6PO_VALID_RHINFO;
break;
}
diff --git a/sys/netinet6/ip6_var.h b/sys/netinet6/ip6_var.h
--- a/sys/netinet6/ip6_var.h
+++ b/sys/netinet6/ip6_var.h
@@ -130,27 +130,26 @@
#define ip6po_nexthop ip6po_nhinfo.ip6po_nhi_nexthop
#define ip6po_nextroute ip6po_nhinfo.ip6po_nhi_route
+/*
+ * Note that fields with valid data must be flagged in ip6po_valid.
+ * This is done to reduce cache misses in ip6_output(). Before
+ * ip6po_valid, ip6_output needed to check all the individual fields
+ * of ip6_pktopts needed to be checked themselves, and they are spread
+ * across 4 cachelines. ip6_output() is currently the only consumer of
+ * these flags, as it is in the critical path of every packet sent.
+ */
struct ip6_pktopts {
- struct mbuf *ip6po_m; /* Pointer to mbuf storing the data */
- int ip6po_hlim; /* Hoplimit for outgoing packets */
-
- /* Outgoing IF/address information */
- struct in6_pktinfo *ip6po_pktinfo;
-
- /* Next-hop address information */
- struct ip6po_nhinfo ip6po_nhinfo;
-
- struct ip6_hbh *ip6po_hbh; /* Hop-by-Hop options header */
-
- /* Destination options header (before a routing header) */
- struct ip6_dest *ip6po_dest1;
-
- /* Routing header related info. */
- struct ip6po_rhinfo ip6po_rhinfo;
-
- /* Destination options header (after a routing header) */
- struct ip6_dest *ip6po_dest2;
+ uint32_t ip6po_valid;
+#define IP6PO_VALID_HLIM 0x0001
+#define IP6PO_VALID_PKTINFO 0x0002
+#define IP6PO_VALID_NHINFO 0x0004
+#define IP6PO_VALID_HBH 0x0008
+#define IP6PO_VALID_DEST1 0x0010
+#define IP6PO_VALID_RHINFO 0x0020
+#define IP6PO_VALID_DEST2 0x0040
+#define IP6PO_VALID_TC 0x0080
+ int ip6po_hlim; /* Hoplimit for outgoing packets */
int ip6po_tclass; /* traffic class */
int ip6po_minmtu; /* fragment vs PMTU discovery policy */
@@ -171,6 +170,25 @@
#endif
#define IP6PO_DONTFRAG 0x04 /* disable fragmentation (IPV6_DONTFRAG) */
#define IP6PO_USECOA 0x08 /* use care of address */
+
+ struct mbuf *ip6po_m; /* Pointer to mbuf storing the data */
+
+ /* Outgoing IF/address information */
+ struct in6_pktinfo *ip6po_pktinfo;
+
+ /* Next-hop address information */
+ struct ip6po_nhinfo ip6po_nhinfo;
+
+ struct ip6_hbh *ip6po_hbh; /* Hop-by-Hop options header */
+
+ /* Destination options header (before a routing header) */
+ struct ip6_dest *ip6po_dest1;
+
+ /* Routing header related info. */
+ struct ip6po_rhinfo ip6po_rhinfo;
+
+ /* Destination options header (after a routing header) */
+ struct ip6_dest *ip6po_dest2;
};
/*
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Apr 28, 12:20 PM (3 h, 29 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
17829963
Default Alt Text
D44204.diff (8 KB)
Attached To
Mode
D44204: ip6_output: Reduce cache misses on pktopts
Attached
Detach File
Event Timeline
Log In to Comment