diff options
-rw-r--r-- | drivers/net/bonding/bond_main.c | 10 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 3 | ||||
-rw-r--r-- | drivers/net/team/team.c | 25 | ||||
-rw-r--r-- | drivers/net/tun.c | 40 | ||||
-rw-r--r-- | drivers/net/usb/asix_devices.c | 3 | ||||
-rw-r--r-- | drivers/net/usb/ax88179_178a.c | 3 | ||||
-rw-r--r-- | drivers/net/usb/usbnet.c | 54 | ||||
-rw-r--r-- | drivers/net/virtio_net.c | 42 | ||||
-rw-r--r-- | include/linux/usb/usbnet.h | 3 | ||||
-rw-r--r-- | include/net/sctp/checksum.h | 15 | ||||
-rw-r--r-- | include/uapi/linux/virtio_net.h | 4 | ||||
-rw-r--r-- | net/bridge/br_device.c | 12 | ||||
-rw-r--r-- | net/bridge/br_if.c | 3 | ||||
-rw-r--r-- | net/bridge/br_private.h | 10 | ||||
-rw-r--r-- | net/netfilter/ipvs/ip_vs_proto_sctp.c | 23 | ||||
-rw-r--r-- | net/netfilter/nf_nat_proto_sctp.c | 8 | ||||
-rw-r--r-- | net/sctp/input.c | 10 |
17 files changed, 166 insertions, 102 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 414d07ef6540..f58435242c50 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -273,7 +273,7 @@ const char *bond_mode_name(int mode) [BOND_MODE_ALB] = "adaptive load balancing", }; - if (mode < 0 || mode > BOND_MODE_ALB) + if (mode < BOND_MODE_ROUNDROBIN || mode > BOND_MODE_ALB) return "unknown"; return names[mode]; @@ -1245,12 +1245,6 @@ static int bond_netpoll_setup(struct net_device *dev, struct netpoll_info *ni, g } return err; } - -static struct netpoll_info *bond_netpoll_info(struct bonding *bond) -{ - return bond->dev->npinfo; -} - #else static inline int slave_enable_netpoll(struct slave *slave) { @@ -1795,7 +1789,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) bond_set_carrier(bond); #ifdef CONFIG_NET_POLL_CONTROLLER - slave_dev->npinfo = bond_netpoll_info(bond); + slave_dev->npinfo = bond->dev->npinfo; if (slave_dev->npinfo) { if (slave_enable_netpoll(new_slave)) { read_unlock(&bond->lock); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c index 03de76c7a177..da8be6e63096 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c @@ -109,9 +109,6 @@ static int stmmac_pltfr_probe(struct platform_device *pdev) const char *mac = NULL; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return -ENODEV; - addr = devm_ioremap_resource(dev, res); if (IS_ERR(addr)) return PTR_ERR(addr); diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index 75159e4184fd..9ccccd40c410 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@ -1037,6 +1037,9 @@ static int team_port_enable_netpoll(struct team *team, struct team_port *port, struct netpoll *np; int err; + if (!team->dev->npinfo) + return 0; + np = kzalloc(sizeof(*np), gfp); if (!np) return -ENOMEM; @@ -1063,12 +1066,6 @@ static void team_port_disable_netpoll(struct team_port *port) __netpoll_cleanup(np); kfree(np); } - -static struct netpoll_info *team_netpoll_info(struct team *team) -{ - return team->dev->npinfo; -} - #else static int team_port_enable_netpoll(struct team *team, struct team_port *port, gfp_t gfp) @@ -1078,10 +1075,6 @@ static int team_port_enable_netpoll(struct team *team, struct team_port *port, static void team_port_disable_netpoll(struct team_port *port) { } -static struct netpoll_info *team_netpoll_info(struct team *team) -{ - return NULL; -} #endif static void __team_port_change_port_added(struct team_port *port, bool linkup); @@ -1163,13 +1156,11 @@ static int team_port_add(struct team *team, struct net_device *port_dev) goto err_vids_add; } - if (team_netpoll_info(team)) { - err = team_port_enable_netpoll(team, port, GFP_KERNEL); - if (err) { - netdev_err(dev, "Failed to enable netpoll on device %s\n", - portname); - goto err_enable_netpoll; - } + err = team_port_enable_netpoll(team, port, GFP_KERNEL); + if (err) { + netdev_err(dev, "Failed to enable netpoll on device %s\n", + portname); + goto err_enable_netpoll; } err = netdev_master_upper_dev_link(port_dev, dev); diff --git a/drivers/net/tun.c b/drivers/net/tun.c index a72d141047cb..5dce262f538e 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -60,6 +60,7 @@ #include <linux/if_arp.h> #include <linux/if_ether.h> #include <linux/if_tun.h> +#include <linux/if_vlan.h> #include <linux/crc32.h> #include <linux/nsproxy.h> #include <linux/virtio_net.h> @@ -1265,6 +1266,7 @@ static ssize_t tun_put_user(struct tun_struct *tun, { struct tun_pi pi = { 0, skb->protocol }; ssize_t total = 0; + int vlan_offset = 0; if (!(tun->flags & TUN_NO_PI)) { if ((len -= sizeof(pi)) < 0) @@ -1328,11 +1330,40 @@ static ssize_t tun_put_user(struct tun_struct *tun, total += tun->vnet_hdr_sz; } - len = min_t(int, skb->len, len); + if (!vlan_tx_tag_present(skb)) { + len = min_t(int, skb->len, len); + } else { + int copy, ret; + struct { + __be16 h_vlan_proto; + __be16 h_vlan_TCI; + } veth; + + veth.h_vlan_proto = skb->vlan_proto; + veth.h_vlan_TCI = htons(vlan_tx_tag_get(skb)); + + vlan_offset = offsetof(struct vlan_ethhdr, h_vlan_proto); + len = min_t(int, skb->len + VLAN_HLEN, len); + + copy = min_t(int, vlan_offset, len); + ret = skb_copy_datagram_const_iovec(skb, 0, iv, total, copy); + len -= copy; + total += copy; + if (ret || !len) + goto done; + + copy = min_t(int, sizeof(veth), len); + ret = memcpy_toiovecend(iv, (void *)&veth, total, copy); + len -= copy; + total += copy; + if (ret || !len) + goto done; + } - skb_copy_datagram_const_iovec(skb, 0, iv, total, len); - total += skb->len; + skb_copy_datagram_const_iovec(skb, vlan_offset, iv, total, len); + total += len; +done: tun->dev->stats.tx_packets++; tun->dev->stats.tx_bytes += len; @@ -1691,7 +1722,8 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) tun_flow_init(tun); dev->hw_features = NETIF_F_SG | NETIF_F_FRAGLIST | - TUN_USER_FEATURES; + TUN_USER_FEATURES | NETIF_F_HW_VLAN_CTAG_TX | + NETIF_F_HW_VLAN_STAG_TX; dev->features = dev->hw_features; dev->vlan_features = dev->features; diff --git a/drivers/net/usb/asix_devices.c b/drivers/net/usb/asix_devices.c index ad5d1e4384db..b96ad4f15b8a 100644 --- a/drivers/net/usb/asix_devices.c +++ b/drivers/net/usb/asix_devices.c @@ -778,6 +778,9 @@ static int ax88178_change_mtu(struct net_device *net, int new_mtu) dev->hard_mtu = net->mtu + net->hard_header_len; ax88178_set_mfb(dev); + /* max qlen depend on hard_mtu and rx_urb_size */ + usbnet_update_max_qlen(dev); + return 0; } diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c index 1e3c302d94fe..658540433faf 100644 --- a/drivers/net/usb/ax88179_178a.c +++ b/drivers/net/usb/ax88179_178a.c @@ -688,6 +688,9 @@ static int ax88179_change_mtu(struct net_device *net, int new_mtu) 2, 2, &tmp16); } + /* max qlen depend on hard_mtu and rx_urb_size */ + usbnet_update_max_qlen(dev); + return 0; } diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 06ee82f557d4..e4811d7b5af1 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -59,15 +59,13 @@ * For high speed, each frame comfortably fits almost 36 max size * Ethernet packets (so queues should be bigger). * - * REVISIT qlens should be members of 'struct usbnet'; the goal is to - * let the USB host controller be busy for 5msec or more before an irq - * is required, under load. Jumbograms change the equation. + * The goal is to let the USB host controller be busy for 5msec or + * more before an irq is required, under load. Jumbograms change + * the equation. */ -#define RX_MAX_QUEUE_MEMORY (60 * 1518) -#define RX_QLEN(dev) (((dev)->udev->speed == USB_SPEED_HIGH) ? \ - (RX_MAX_QUEUE_MEMORY/(dev)->rx_urb_size) : 4) -#define TX_QLEN(dev) (((dev)->udev->speed == USB_SPEED_HIGH) ? \ - (RX_MAX_QUEUE_MEMORY/(dev)->hard_mtu) : 4) +#define MAX_QUEUE_MEMORY (60 * 1518) +#define RX_QLEN(dev) ((dev)->rx_qlen) +#define TX_QLEN(dev) ((dev)->tx_qlen) // reawaken network queue this soon after stopping; else watchdog barks #define TX_TIMEOUT_JIFFIES (5*HZ) @@ -347,6 +345,31 @@ void usbnet_skb_return (struct usbnet *dev, struct sk_buff *skb) } EXPORT_SYMBOL_GPL(usbnet_skb_return); +/* must be called if hard_mtu or rx_urb_size changed */ +void usbnet_update_max_qlen(struct usbnet *dev) +{ + enum usb_device_speed speed = dev->udev->speed; + + switch (speed) { + case USB_SPEED_HIGH: + dev->rx_qlen = MAX_QUEUE_MEMORY / dev->rx_urb_size; + dev->tx_qlen = MAX_QUEUE_MEMORY / dev->hard_mtu; + break; + case USB_SPEED_SUPER: + /* + * Not take default 5ms qlen for super speed HC to + * save memory, and iperf tests show 2.5ms qlen can + * work well + */ + dev->rx_qlen = 5 * MAX_QUEUE_MEMORY / dev->rx_urb_size; + dev->tx_qlen = 5 * MAX_QUEUE_MEMORY / dev->hard_mtu; + break; + default: + dev->rx_qlen = dev->tx_qlen = 4; + } +} +EXPORT_SYMBOL_GPL(usbnet_update_max_qlen); + /*------------------------------------------------------------------------- * @@ -375,6 +398,9 @@ int usbnet_change_mtu (struct net_device *net, int new_mtu) usbnet_unlink_rx_urbs(dev); } + /* max qlen depend on hard_mtu and rx_urb_size */ + usbnet_update_max_qlen(dev); + return 0; } EXPORT_SYMBOL_GPL(usbnet_change_mtu); @@ -843,6 +869,9 @@ int usbnet_open (struct net_device *net) goto done; } + /* hard_mtu or rx_urb_size may change in reset() */ + usbnet_update_max_qlen(dev); + // insist peer be connected if (info->check_connect && (retval = info->check_connect (dev)) < 0) { netif_dbg(dev, ifup, dev->net, "can't open; %d\n", retval); @@ -927,6 +956,9 @@ int usbnet_set_settings (struct net_device *net, struct ethtool_cmd *cmd) if (dev->driver_info->link_reset) dev->driver_info->link_reset(dev); + /* hard_mtu or rx_urb_size may change in link_reset() */ + usbnet_update_max_qlen(dev); + return retval; } @@ -1020,6 +1052,9 @@ static void __handle_link_change(struct usbnet *dev) tasklet_schedule(&dev->bh); } + /* hard_mtu or rx_urb_size may change during link change */ + usbnet_update_max_qlen(dev); + clear_bit(EVENT_LINK_CHANGE, &dev->flags); } @@ -1599,6 +1634,9 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) if ((dev->driver_info->flags & FLAG_WWAN) != 0) SET_NETDEV_DEVTYPE(net, &wwan_type); + /* initialize max rx_qlen and tx_qlen */ + usbnet_update_max_qlen(dev); + status = register_netdev (net); if (status) goto out4; diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 3d2a90a62649..f21600277583 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -106,6 +106,9 @@ struct virtnet_info { /* Has control virtqueue */ bool has_cvq; + /* Host can handle any s/g split between our header and packet data */ + bool any_header_sg; + /* enable config space updates */ bool config_enable; @@ -669,12 +672,28 @@ static void free_old_xmit_skbs(struct send_queue *sq) static int xmit_skb(struct send_queue *sq, struct sk_buff *skb) { - struct skb_vnet_hdr *hdr = skb_vnet_hdr(skb); + struct skb_vnet_hdr *hdr; const unsigned char *dest = ((struct ethhdr *)skb->data)->h_dest; struct virtnet_info *vi = sq->vq->vdev->priv; unsigned num_sg; + unsigned hdr_len; + bool can_push; pr_debug("%s: xmit %p %pM\n", vi->dev->name, skb, dest); + if (vi->mergeable_rx_bufs) + hdr_len = sizeof hdr->mhdr; + else + hdr_len = sizeof hdr->hdr; + + can_push = vi->any_header_sg && + !((unsigned long)skb->data & (__alignof__(*hdr) - 1)) && + !skb_header_cloned(skb) && skb_headroom(skb) >= hdr_len; + /* Even if we can, don't push here yet as this would skew + * csum_start offset below. */ + if (can_push) + hdr = (struct skb_vnet_hdr *)(skb->data - hdr_len); + else + hdr = skb_vnet_hdr(skb); if (skb->ip_summed == CHECKSUM_PARTIAL) { hdr->hdr.flags = VIRTIO_NET_HDR_F_NEEDS_CSUM; @@ -703,15 +722,18 @@ static int xmit_skb(struct send_queue *sq, struct sk_buff *skb) hdr->hdr.gso_size = hdr->hdr.hdr_len = 0; } - hdr->mhdr.num_buffers = 0; - - /* Encode metadata header at front. */ if (vi->mergeable_rx_bufs) - sg_set_buf(sq->sg, &hdr->mhdr, sizeof hdr->mhdr); - else - sg_set_buf(sq->sg, &hdr->hdr, sizeof hdr->hdr); + hdr->mhdr.num_buffers = 0; - num_sg = skb_to_sgvec(skb, sq->sg + 1, 0, skb->len) + 1; + if (can_push) { + __skb_push(skb, hdr_len); + num_sg = skb_to_sgvec(skb, sq->sg, 0, skb->len); + /* Pull header back to avoid skew in tx bytes calculations. */ + __skb_pull(skb, hdr_len); + } else { + sg_set_buf(sq->sg, hdr, hdr_len); + num_sg = skb_to_sgvec(skb, sq->sg + 1, 0, skb->len) + 1; + } return virtqueue_add_outbuf(sq->vq, sq->sg, num_sg, skb, GFP_ATOMIC); } @@ -1552,6 +1574,9 @@ static int virtnet_probe(struct virtio_device *vdev) if (virtio_has_feature(vdev, VIRTIO_NET_F_MRG_RXBUF)) vi->mergeable_rx_bufs = true; + if (virtio_has_feature(vdev, VIRTIO_F_ANY_LAYOUT)) + vi->any_header_sg = true; + if (virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_VQ)) vi->has_cvq = true; @@ -1727,6 +1752,7 @@ static unsigned int features[] = { VIRTIO_NET_F_CTRL_RX, VIRTIO_NET_F_CTRL_VLAN, VIRTIO_NET_F_GUEST_ANNOUNCE, VIRTIO_NET_F_MQ, VIRTIO_NET_F_CTRL_MAC_ADDR, + VIRTIO_F_ANY_LAYOUT, }; static struct virtio_driver virtio_net_driver = { diff --git a/include/linux/usb/usbnet.h b/include/linux/usb/usbnet.h index f18d64129f99..8fbc008e183e 100644 --- a/include/linux/usb/usbnet.h +++ b/include/linux/usb/usbnet.h @@ -34,6 +34,7 @@ struct usbnet { struct mutex phy_mutex; unsigned char suspend_count; unsigned char pkt_cnt, pkt_err; + unsigned short rx_qlen, tx_qlen; /* i/o info: pipes etc */ unsigned in, out; @@ -253,4 +254,6 @@ extern void usbnet_link_change(struct usbnet *, bool, bool); extern int usbnet_status_start(struct usbnet *dev, gfp_t mem_flags); extern void usbnet_status_stop(struct usbnet *dev); +extern void usbnet_update_max_qlen(struct usbnet *dev); + #endif /* __LINUX_USB_USBNET_H */ diff --git a/include/net/sctp/checksum.h b/include/net/sctp/checksum.h index 78b88aa8c810..483e6303458d 100644 --- a/include/net/sctp/checksum.h +++ b/include/net/sctp/checksum.h @@ -85,4 +85,19 @@ static inline __le32 sctp_end_cksum(__u32 crc32) return cpu_to_le32(~crc32); } +/* Calculate the CRC32C checksum of an SCTP packet. */ +static inline __le32 sctp_compute_cksum(const struct sk_buff *skb, + unsigned int offset) +{ + const struct sk_buff *iter; + + __u32 crc32 = sctp_start_cksum(skb->data + offset, + skb_headlen(skb) - offset); + skb_walk_frags(skb, iter) + crc32 = sctp_update_cksum((__u8 *) iter->data, + skb_headlen(iter), crc32); + + return sctp_end_cksum(crc32); +} + #endif /* __sctp_checksum_h__ */ diff --git a/include/uapi/linux/virtio_net.h b/include/uapi/linux/virtio_net.h index c520203fac2f..227d4ce84e79 100644 --- a/include/uapi/linux/virtio_net.h +++ b/include/uapi/linux/virtio_net.h @@ -70,7 +70,9 @@ struct virtio_net_config { __u16 max_virtqueue_pairs; } __attribute__((packed)); -/* This is the first element of the scatter-gather list. If you don't +/* This header comes first in the scatter-gather list. + * If VIRTIO_F_ANY_LAYOUT is not negotiated, it must + * be the first element of the scatter-gather list. If you don't * specify GSO or CSUM features, you can simply ignore the header. */ struct virtio_net_hdr { #define VIRTIO_NET_HDR_F_NEEDS_CSUM 1 // Use csum_start, csum_offset diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index 2ef66781fedb..50d86b3e3941 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c @@ -244,22 +244,22 @@ fail: int br_netpoll_enable(struct net_bridge_port *p, gfp_t gfp) { struct netpoll *np; - int err = 0; + int err; + + if (!p->br->dev->npinfo) + return 0; np = kzalloc(sizeof(*p->np), gfp); - err = -ENOMEM; if (!np) - goto out; + return -ENOMEM; err = __netpoll_setup(np, p->dev, gfp); if (err) { kfree(np); - goto out; + return err; } p->np = np; - -out: return err; } diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 5623be6b9ecd..aa6c9a8ba32a 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -363,7 +363,8 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) if (err) goto err2; - if (br_netpoll_info(br) && ((err = br_netpoll_enable(p, GFP_KERNEL)))) + err = br_netpoll_enable(p, GFP_KERNEL); + if (err) goto err3; err = netdev_master_upper_dev_link(dev, br->dev); diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 3be89b3ce17b..43347f129943 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -333,11 +333,6 @@ extern void br_dev_delete(struct net_device *dev, struct list_head *list); extern netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev); #ifdef CONFIG_NET_POLL_CONTROLLER -static inline struct netpoll_info *br_netpoll_info(struct net_bridge *br) -{ - return br->dev->npinfo; -} - static inline void br_netpoll_send_skb(const struct net_bridge_port *p, struct sk_buff *skb) { @@ -350,11 +345,6 @@ static inline void br_netpoll_send_skb(const struct net_bridge_port *p, extern int br_netpoll_enable(struct net_bridge_port *p, gfp_t gfp); extern void br_netpoll_disable(struct net_bridge_port *p); #else -static inline struct netpoll_info *br_netpoll_info(struct net_bridge *br) -{ - return NULL; -} - static inline void br_netpoll_send_skb(const struct net_bridge_port *p, struct sk_buff *skb) { diff --git a/net/netfilter/ipvs/ip_vs_proto_sctp.c b/net/netfilter/ipvs/ip_vs_proto_sctp.c index 3c0da8728036..23e596e438b3 100644 --- a/net/netfilter/ipvs/ip_vs_proto_sctp.c +++ b/net/netfilter/ipvs/ip_vs_proto_sctp.c @@ -66,15 +66,7 @@ sctp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd, static void sctp_nat_csum(struct sk_buff *skb, sctp_sctphdr_t *sctph, unsigned int sctphoff) { - __u32 crc32; - struct sk_buff *iter; - - crc32 = sctp_start_cksum((__u8 *)sctph, skb_headlen(skb) - sctphoff); - skb_walk_frags(skb, iter) - crc32 = sctp_update_cksum((u8 *) iter->data, - skb_headlen(iter), crc32); - sctph->checksum = sctp_end_cksum(crc32); - + sctph->checksum = sctp_compute_cksum(skb, sctphoff); skb->ip_summed = CHECKSUM_UNNECESSARY; } @@ -151,10 +143,7 @@ sctp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp) { unsigned int sctphoff; struct sctphdr *sh, _sctph; - struct sk_buff *iter; - __le32 cmp; - __le32 val; - __u32 tmp; + __le32 cmp, val; #ifdef CONFIG_IP_VS_IPV6 if (af == AF_INET6) @@ -168,13 +157,7 @@ sctp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp) return 0; cmp = sh->checksum; - - tmp = sctp_start_cksum((__u8 *) sh, skb_headlen(skb)); - skb_walk_frags(skb, iter) - tmp = sctp_update_cksum((__u8 *) iter->data, - skb_headlen(iter), tmp); - - val = sctp_end_cksum(tmp); + val = sctp_compute_cksum(skb, sctphoff); if (val != cmp) { /* CRC failure, dump it. */ diff --git a/net/netfilter/nf_nat_proto_sctp.c b/net/netfilter/nf_nat_proto_sctp.c index 396e55d46f90..754536f2c674 100644 --- a/net/netfilter/nf_nat_proto_sctp.c +++ b/net/netfilter/nf_nat_proto_sctp.c @@ -34,9 +34,7 @@ sctp_manip_pkt(struct sk_buff *skb, const struct nf_conntrack_tuple *tuple, enum nf_nat_manip_type maniptype) { - struct sk_buff *frag; sctp_sctphdr_t *hdr; - __u32 crc32; if (!skb_make_writable(skb, hdroff + sizeof(*hdr))) return false; @@ -51,11 +49,7 @@ sctp_manip_pkt(struct sk_buff *skb, hdr->dest = tuple->dst.u.sctp.port; } - crc32 = sctp_start_cksum((u8 *)hdr, skb_headlen(skb) - hdroff); - skb_walk_frags(skb, frag) - crc32 = sctp_update_cksum((u8 *)frag->data, skb_headlen(frag), - crc32); - hdr->checksum = sctp_end_cksum(crc32); + hdr->checksum = sctp_compute_cksum(skb, hdroff); return true; } diff --git a/net/sctp/input.c b/net/sctp/input.c index 7993495a4c0f..fa91aff02388 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c @@ -87,15 +87,7 @@ static inline int sctp_rcv_checksum(struct net *net, struct sk_buff *skb) { struct sctphdr *sh = sctp_hdr(skb); __le32 cmp = sh->checksum; - struct sk_buff *list; - __le32 val; - __u32 tmp = sctp_start_cksum((__u8 *)sh, skb_headlen(skb)); - - skb_walk_frags(skb, list) - tmp = sctp_update_cksum((__u8 *)list->data, skb_headlen(list), - tmp); - - val = sctp_end_cksum(tmp); + __le32 val = sctp_compute_cksum(skb, 0); if (val != cmp) { /* CRC failure, dump it. */ |