X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=datapath%2Fdatapath.c;h=6365f9474564dbac9c7be08d6c697a416bda155b;hb=7c88a5dc3ac1a034552bb94d42394bd325c1204e;hp=b6aefe892156fb3cbc887bd3d897c78140574bb4;hpb=a063b0dff0ccb6639f7e95969843d1c7cc2e15ae;p=openvswitch diff --git a/datapath/datapath.c b/datapath/datapath.c index b6aefe89..6365f947 100644 --- a/datapath/datapath.c +++ b/datapath/datapath.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include "openvswitch/datapath-protocol.h" @@ -71,7 +72,6 @@ static DEFINE_MUTEX(dp_mutex); #define MAINT_SLEEP_MSECS 1000 static int new_nbp(struct datapath *, struct net_device *, int port_no); -static void compute_ip_summed(struct sk_buff *skb); /* Must be called with rcu_read_lock or dp_mutex. */ struct datapath *get_dp(int dp_idx) @@ -359,6 +359,7 @@ static int new_nbp(struct datapath *dp, struct net_device *dev, int port_no) * in dp_frame_hook(). In turn dp_frame_hook() can reject them * back to network stack, but that's a waste of time. */ } + dev_disable_lro(dev); rcu_assign_pointer(dp->ports[port_no], p); list_add_rcu(&p->node, &dp->port_list); dp->n_ports++; @@ -506,6 +507,11 @@ out: static void do_port_input(struct net_bridge_port *p, struct sk_buff *skb) { + /* LRO isn't suitable for bridging. We turn it off but make sure + * that it wasn't reactivated. */ + if (skb_warn_if_lro(skb)) + return; + /* Make our own copy of the packet. Otherwise we will mangle the * packet for anyone who came before us (e.g. tcpdump via AF_PACKET). * (No one comes after us, since we tell handle_bridge() that we took @@ -530,7 +536,7 @@ void dp_process_received_packet(struct sk_buff *skb, struct net_bridge_port *p) WARN_ON_ONCE(skb_shared(skb)); - compute_ip_summed(skb); + 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()); @@ -699,25 +705,57 @@ out: * 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.*/ -static void -compute_ip_summed(struct sk_buff *skb) +void +compute_ip_summed(struct sk_buff *skb, bool xmit) { - OVS_CB(skb)->ip_summed = skb->ip_summed; - + /* For our convenience these defines change repeatedly between kernel + * versions, so we can't just copy them over... */ + switch (skb->ip_summed) { + case CHECKSUM_NONE: + OVS_CB(skb)->ip_summed = OVS_CSUM_NONE; + break; + case CHECKSUM_UNNECESSARY: + OVS_CB(skb)->ip_summed = OVS_CSUM_UNNECESSARY; + 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. */ - if (skb->ip_summed == CHECKSUM_HW) - OVS_CB(skb)->ip_summed = CSUM_COMPLETE; + * 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. */ + case CHECKSUM_HW: + if (!xmit) + OVS_CB(skb)->ip_summed = OVS_CSUM_COMPLETE; + else + OVS_CB(skb)->ip_summed = OVS_CSUM_PARTIAL; + + break; +#else + case CHECKSUM_COMPLETE: + OVS_CB(skb)->ip_summed = OVS_CSUM_COMPLETE; + break; + case CHECKSUM_PARTIAL: + OVS_CB(skb)->ip_summed = OVS_CSUM_PARTIAL; + break; #endif + default: + printk(KERN_ERR "openvswitch: unknown checksum type %d\n", + skb->ip_summed); + /* None seems the safest... */ + OVS_CB(skb)->ip_summed = OVS_CSUM_NONE; + } + #if defined(CONFIG_XEN) && defined(HAVE_PROTO_DATA_VALID) /* Xen has a special way of representing CHECKSUM_PARTIAL on older - * kernels. */ + * kernels. It should not be set on the transmit path though. */ if (skb->proto_csum_blank) - OVS_CB(skb)->ip_summed = CSUM_PARTIAL; + OVS_CB(skb)->ip_summed = OVS_CSUM_PARTIAL; + + WARN_ON_ONCE(skb->proto_csum_blank && xmit); #endif } @@ -725,7 +763,7 @@ void forward_ip_summed(struct sk_buff *skb) { #ifdef CHECKSUM_HW - if (OVS_CB(skb)->ip_summed == CSUM_COMPLETE) + if (OVS_CB(skb)->ip_summed == OVS_CSUM_COMPLETE) skb->ip_summed = CHECKSUM_NONE; #endif } @@ -893,6 +931,11 @@ static int validate_actions(const struct sw_flow_actions *actions) return -EINVAL; break; + case ODPAT_SET_NW_TOS: + if (a->nw_tos.nw_tos & INET_ECN_MASK) + return -EINVAL; + break; + default: if (a->type >= ODPAT_N_ACTIONS) return -EOPNOTSUPP;