aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/netdevice.h
diff options
context:
space:
mode:
authorTom Herbert <tom@herbertland.com>2015-12-14 11:19:46 -0800
committerDavid S. Miller <davem@davemloft.net>2015-12-15 16:50:21 -0500
commit6ae23ad36253a8033c5714c52b691b84456487c5 (patch)
treec595df47ba28d6fca8f1deb338c8256d6123c77b /include/linux/netdevice.h
parenttcp: Fix conditions to determine checksum offload (diff)
downloadlinux-dev-6ae23ad36253a8033c5714c52b691b84456487c5.tar.xz
linux-dev-6ae23ad36253a8033c5714c52b691b84456487c5.zip
net: Add driver helper functions to determine checksum offloadability
Add skb_csum_offload_chk driver helper function to determine if a device with limited checksum offload capabilities is able to offload the checksum for a given packet. This patch includes: - The skb_csum_offload_chk function. Returns true if checksum is offloadable, else false. Optionally, in the case that the checksum is not offloable, the function can call skb_checksum_help to resolve the checksum. skb_csum_offload_chk also returns whether the checksum refers to an encapsulated checksum. - Definition of skb_csum_offl_spec structure that caller uses to indicate rules about what it can offload (e.g. IPv4/v6, TCP/UDP only, whether encapsulated checksums can be offloaded, whether checksum with IPv6 extension headers can be offloaded). - Ancilary functions called skb_csum_offload_chk_help, skb_csum_off_chk_help_cmn, skb_csum_off_chk_help_cmn_v4_only. Signed-off-by: Tom Herbert <tom@herbertland.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/linux/netdevice.h')
-rw-r--r--include/linux/netdevice.h78
1 files changed, 78 insertions, 0 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 283984b67cd9..9fb6395967de 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2522,6 +2522,71 @@ static inline void skb_gro_remcsum_cleanup(struct sk_buff *skb,
remcsum_unadjust((__sum16 *)ptr, grc->delta);
}
+struct skb_csum_offl_spec {
+ __u16 ipv4_okay:1,
+ ipv6_okay:1,
+ encap_okay:1,
+ ip_options_okay:1,
+ ext_hdrs_okay:1,
+ tcp_okay:1,
+ udp_okay:1,
+ sctp_okay:1,
+ vlan_okay:1,
+ no_encapped_ipv6:1,
+ no_not_encapped:1;
+};
+
+bool __skb_csum_offload_chk(struct sk_buff *skb,
+ const struct skb_csum_offl_spec *spec,
+ bool *csum_encapped,
+ bool csum_help);
+
+static inline bool skb_csum_offload_chk(struct sk_buff *skb,
+ const struct skb_csum_offl_spec *spec,
+ bool *csum_encapped,
+ bool csum_help)
+{
+ if (skb->ip_summed != CHECKSUM_PARTIAL)
+ return false;
+
+ return __skb_csum_offload_chk(skb, spec, csum_encapped, csum_help);
+}
+
+static inline bool skb_csum_offload_chk_help(struct sk_buff *skb,
+ const struct skb_csum_offl_spec *spec)
+{
+ bool csum_encapped;
+
+ return skb_csum_offload_chk(skb, spec, &csum_encapped, true);
+}
+
+static inline bool skb_csum_off_chk_help_cmn(struct sk_buff *skb)
+{
+ static const struct skb_csum_offl_spec csum_offl_spec = {
+ .ipv4_okay = 1,
+ .ip_options_okay = 1,
+ .ipv6_okay = 1,
+ .vlan_okay = 1,
+ .tcp_okay = 1,
+ .udp_okay = 1,
+ };
+
+ return skb_csum_offload_chk_help(skb, &csum_offl_spec);
+}
+
+static inline bool skb_csum_off_chk_help_cmn_v4_only(struct sk_buff *skb)
+{
+ static const struct skb_csum_offl_spec csum_offl_spec = {
+ .ipv4_okay = 1,
+ .ip_options_okay = 1,
+ .tcp_okay = 1,
+ .udp_okay = 1,
+ .vlan_okay = 1,
+ };
+
+ return skb_csum_offload_chk_help(skb, &csum_offl_spec);
+}
+
static inline int dev_hard_header(struct sk_buff *skb, struct net_device *dev,
unsigned short type,
const void *daddr, const void *saddr,
@@ -3711,6 +3776,19 @@ static inline bool can_checksum_protocol(netdev_features_t features,
}
}
+/* Map an ethertype into IP protocol if possible */
+static inline int eproto_to_ipproto(int eproto)
+{
+ switch (eproto) {
+ case htons(ETH_P_IP):
+ return IPPROTO_IP;
+ case htons(ETH_P_IPV6):
+ return IPPROTO_IPV6;
+ default:
+ return -1;
+ }
+}
+
#ifdef CONFIG_BUG
void netdev_rx_csum_fault(struct net_device *dev);
#else