X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=datapath%2Fdatapath.c;h=79a1f63251f7ece61613e81f6738603af7e7db86;hb=f4267e344a9373a4efefff8f8f5b85f532d223e1;hp=be16044d5a44a60ab6a751273187827aedbee8cc;hpb=1224e8fc1da9cddef6bdb24814300893bb2ace89;p=openvswitch diff --git a/datapath/datapath.c b/datapath/datapath.c index be16044d..79a1f632 100644 --- a/datapath/datapath.c +++ b/datapath/datapath.c @@ -202,10 +202,14 @@ static int create_dp(int dp_idx, const char __user *devnamep) int i; if (devnamep) { - err = -EFAULT; - if (strncpy_from_user(devname, devnamep, IFNAMSIZ) < 0) + int retval = strncpy_from_user(devname, devnamep, IFNAMSIZ); + if (retval < 0) { + err = -EFAULT; goto err; - devname[IFNAMSIZ - 1] = '\0'; + } else if (retval >= IFNAMSIZ) { + err = -ENAMETOOLONG; + goto err; + } } else { snprintf(devname, sizeof devname, "of%d", dp_idx); } @@ -246,7 +250,8 @@ static int create_dp(int dp_idx, const char __user *devnamep) goto err_free_dp; /* Set up our datapath device. */ - strncpy(internal_dev_port.devname, devname, IFNAMSIZ - 1); + BUILD_BUG_ON(sizeof(internal_dev_port.devname) != sizeof(devname)); + strcpy(internal_dev_port.devname, devname); internal_dev_port.flags = ODP_PORT_INTERNAL; err = new_dp_port(dp, &internal_dev_port, ODPP_LOCAL); if (err) { @@ -423,8 +428,7 @@ got_port_no: if (err) goto out_unlock_dp; - if (!(port.flags & ODP_PORT_INTERNAL)) - set_internal_devs_mtu(dp); + set_internal_devs_mtu(dp); dp_sysfs_add_if(dp->ports[port_no]); err = __put_user(port_no, &portp->port); @@ -518,7 +522,6 @@ void dp_process_received_packet(struct dp_port *p, struct sk_buff *skb) skb_warn_if_lro(skb); OVS_CB(skb)->dp_port = p; - compute_ip_summed(skb, false); /* BHs are off so we don't have to use get_cpu()/put_cpu() here. */ stats = percpu_ptr(dp->stats_percpu, smp_processor_id()); @@ -546,22 +549,9 @@ void dp_process_received_packet(struct dp_port *p, struct sk_buff *skb) } #if defined(CONFIG_XEN) && defined(HAVE_PROTO_DATA_VALID) -/* This code is based on a skb_checksum_setup from net/dev/core.c from a - * combination of Lenny's 2.6.26 Xen kernel and Xen's - * linux-2.6.18-92.1.10.el5.xs5.0.0.394.644. We can't call this function - * directly because it isn't exported in all versions. */ -static int skb_pull_up_to(struct sk_buff *skb, void *ptr) -{ - if (ptr < (void *)skb->tail) - return 1; - if (__pskb_pull_tail(skb, - ptr - (void *)skb->data - skb_headlen(skb))) { - return 1; - } else { - return 0; - } -} - +/* This code is based on skb_checksum_setup() from Xen's net/dev/core.c. We + * can't call this function directly because it isn't exported in all + * versions. */ int vswitch_skb_checksum_setup(struct sk_buff *skb) { struct iphdr *iph; @@ -575,7 +565,7 @@ int vswitch_skb_checksum_setup(struct sk_buff *skb) if (skb->protocol != htons(ETH_P_IP)) goto out; - if (!skb_pull_up_to(skb, skb_network_header(skb) + sizeof(struct iphdr))) + if (!pskb_may_pull(skb, skb_network_header(skb) + sizeof(struct iphdr) - skb->data)) goto out; iph = ip_hdr(skb); @@ -597,7 +587,7 @@ int vswitch_skb_checksum_setup(struct sk_buff *skb) goto out; } - if (!skb_pull_up_to(skb, th + csum_offset + 2)) + if (!pskb_may_pull(skb, th + csum_offset + 2 - skb->data)) goto out; skb->ip_summed = CHECKSUM_PARTIAL; @@ -634,8 +624,7 @@ out: * be computed if it is sent off box. Unfortunately on earlier kernels, * this case is impossible to distinguish from #2, despite having opposite * meanings. Xen adds an extra field on earlier kernels (see #4) in order - * to distinguish the different states. The only real user of this type - * with bridging is Xen (on later kernels). + * to distinguish the different states. * 4. CHECKSUM_UNNECESSARY (with proto_csum_blank true): This packet was * generated locally by a Xen DomU and has a partial checksum. If it is * handled on this machine (Dom0 or DomU), then the checksum will not be @@ -659,12 +648,7 @@ out: * packet is processed by the local IP stack, in which case it will need to * be reverified). If we receive a packet with CHECKSUM_HW that really means * CHECKSUM_PARTIAL, it will be sent with the wrong checksum. However, there - * shouldn't be any devices that do this with bridging. - * - * The bridge has similar behavior and this function closely resembles - * skb_forward_csum(). It is slightly different because we are only concerned - * with bridging and not other types of forwarding and can get away with - * slightly more optimal behavior.*/ + * shouldn't be any devices that do this with bridging. */ void compute_ip_summed(struct sk_buff *skb, bool xmit) { @@ -679,14 +663,14 @@ compute_ip_summed(struct sk_buff *skb, bool xmit) break; #ifdef CHECKSUM_HW /* In theory this could be either CHECKSUM_PARTIAL or CHECKSUM_COMPLETE. - * However, we should only get CHECKSUM_PARTIAL packets from Xen, which - * uses some special fields to represent this (see below). Since we - * can only make one type work, pick the one that actually happens in - * practice. + * However, on the receive side we should only get CHECKSUM_PARTIAL + * packets from Xen, which uses some special fields to represent this + * (see below). Since we can only make one type work, pick the one + * that actually happens in practice. * - * The one exception to this is if we are on the transmit path - * (basically after skb_checksum_setup() has been run) the type has - * already been converted, so we should stay with that. */ + * On the transmit side (basically after skb_checksum_setup() + * has been run or on internal dev transmit), packets with + * CHECKSUM_COMPLETE aren't generated, so assume CHECKSUM_PARTIAL. */ case CHECKSUM_HW: if (!xmit) OVS_CB(skb)->ip_summed = OVS_CSUM_COMPLETE; @@ -719,6 +703,10 @@ compute_ip_summed(struct sk_buff *skb, bool xmit) #endif } +/* This function closely resembles skb_forward_csum() used by the bridge. It + * is slightly different because we are only concerned with bridging and not + * other types of forwarding and can get away with slightly more optimal + * behavior.*/ void forward_ip_summed(struct sk_buff *skb) { @@ -750,9 +738,7 @@ queue_control_packets(struct sk_buff *skb, struct sk_buff_head *queue, skb->next = NULL; /* If a checksum-deferred packet is forwarded to the - * controller, correct the pointers and checksum. This happens - * on a regular basis only on Xen, on which VMs can pass up - * packets that do not have their checksum computed. + * controller, correct the pointers and checksum. */ err = vswitch_skb_checksum_setup(skb); if (err) @@ -1366,7 +1352,7 @@ int dp_min_mtu(const struct datapath *dp) } /* Sets the MTU of all datapath devices to the minimum of the ports. Must - * be called with RTNL lock and dp_mutex. */ + * be called with RTNL lock. */ void set_internal_devs_mtu(const struct datapath *dp) { struct dp_port *p;