get_skb_csum_pointers(skb, &csum_start, &csum_offset);
csum_start -= skb_headroom(skb);
- BUG_ON(csum_start >= skb_headlen(skb));
skb_copy_bits(skb, 0, to, csum_start);
}
}
- return queue_control_packets(dp, skb, upcall_info);
+ err = queue_control_packets(dp, skb, upcall_info);
+ if (err)
+ goto err;
+
+ return 0;
err_kfree_skb:
kfree_skb(skb);
if (unlikely(err))
goto err_kfree_skbs;
+ if (nla_attr_size(skb->len) > USHRT_MAX)
+ goto err_kfree_skbs;
+
len = sizeof(struct odp_header);
len += nla_total_size(skb->len);
len += nla_total_size(FLOW_BUFSIZE);
else
packet->protocol = htons(ETH_P_802_2);
+ /* Initialize OVS_CB (it came from Netlink so might not be zeroed). */
+ memset(OVS_CB(packet), 0, sizeof(struct ovs_skb_cb));
+
err = flow_extract(packet, -1, &key, &is_frag);
if (err)
goto exit;
- /* Initialize OVS_CB (it came from Netlink so might not be zeroed). */
- memset(OVS_CB(packet), 0, sizeof(struct ovs_skb_cb));
-
rcu_read_lock();
dp = get_dp(odp_header->dp_ifindex);
err = -ENODEV;
list_del(&dp->list_node);
dp_detach_port(get_vport_protected(dp, ODPP_LOCAL));
+ /* rtnl_unlock() will wait until all the references to devices that
+ * are pending unregistration have been dropped. We do it here to
+ * ensure that any internal devices (which contain DP pointers) are
+ * fully destroyed before freeing the datapath.
+ */
+ rtnl_unlock();
+
call_rcu(&dp->rcu, destroy_dp_rcu);
module_put(THIS_MODULE);
genl_notify(reply, genl_info_net(info), info->snd_pid,
dp_datapath_multicast_group.id, info->nlhdr, GFP_KERNEL);
- err = 0;
+
+ return 0;
exit_unlock:
rtnl_unlock();