X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=datapath%2Fdatapath.c;h=b25b8996e0735791ca64b7e6638d5d372678c17d;hb=926ea16ea3b38df0f34cdccdea92aa4933ca9dd4;hp=dcff05f2986dbc23749c01063eb47ce3f10b120c;hpb=088a727c9ca2a9b54e11de94e1fc4396a277523a;p=openvswitch diff --git a/datapath/datapath.c b/datapath/datapath.c index dcff05f2..b25b8996 100644 --- a/datapath/datapath.c +++ b/datapath/datapath.c @@ -359,7 +359,6 @@ static void copy_and_csum_skb(struct sk_buff *skb, void *to) 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); @@ -441,7 +440,11 @@ int dp_upcall(struct datapath *dp, struct sk_buff *skb, const struct dp_upcall_i } } - 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); @@ -488,6 +491,9 @@ static int queue_control_packets(struct datapath *dp, struct sk_buff *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); @@ -705,19 +711,13 @@ static int odp_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info) 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). */ - OVS_CB(packet)->vport = NULL; - OVS_CB(packet)->flow = NULL; - /* execute_actions() will reset tun_id to 0 anyhow. */ -#ifdef NEED_CSUM_NORMALIZE - OVS_CB(packet)->ip_summed = OVS_CSUM_NONE; -#endif - vlan_copy_skb_tci(packet); - rcu_read_lock(); dp = get_dp(odp_header->dp_ifindex); err = -ENODEV; @@ -1456,12 +1456,20 @@ static int odp_dp_cmd_del(struct sk_buff *skb, struct genl_info *info) 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();