Thanks, Greg. I pushed the patches you sent for all the appropriate branches (2.5-2.8). I sent out patches to do bug patch releases for all those branches, too, that will include these. Hopefully we'll get those merged and all the releases out tomorrow.
--Justin > On Sep 4, 2019, at 10:07 AM, Greg Rose <gvrose8...@gmail.com> wrote: > > Upstream commit: > commit ad06a566e118e57b852cab5933dbbbaebb141de3 > Author: Greg Rose <gvrose8...@gmail.com> > Date: Tue Aug 27 07:58:09 2019 -0700 > > openvswitch: Properly set L4 keys on "later" IP fragments > > When IP fragments are reassembled before being sent to conntrack, the > key from the last fragment is used. Unless there are reordering > issues, the last fragment received will not contain the L4 ports, so the > key for the reassembled datagram won't contain them. This patch updates > the key once we have a reassembled datagram. > > The handle_fragments() function works on L3 headers so we pull the L3/L4 > flow key update code from key_extract into a new function > 'key_extract_l3l4'. Then we add a another new function > ovs_flow_key_update_l3l4() and export it so that it is accessible by > handle_fragments() for conntrack packet reassembly. > > Co-authored-by: Justin Pettit <jpet...@ovn.org> > Signed-off-by: Greg Rose <gvrose8...@gmail.com> > Acked-by: Pravin B Shelar <pshe...@ovn.org> > Signed-off-by: David S. Miller <da...@davemloft.net> > > Signed-off-by: Greg Rose <gvrose8...@gmail.com> > > --- > > V2 - Fix compile errors > --- > datapath/conntrack.c | 5 ++ > datapath/flow.c | 157 +++++++++++++++++++++++++++++---------------------- > datapath/flow.h | 1 + > 3 files changed, 95 insertions(+), 68 deletions(-) > > diff --git a/datapath/conntrack.c b/datapath/conntrack.c > index 1990984..2c3e441 100644 > --- a/datapath/conntrack.c > +++ b/datapath/conntrack.c > @@ -537,6 +537,11 @@ static int handle_fragments(struct net *net, struct > sw_flow_key *key, > return -EPFNOSUPPORT; > } > > + /* The key extracted from the fragment that completed this datagram > + * likely didn't have an L4 header, so regenerate it. > + */ > + ovs_flow_key_update_l3l4(skb, key); > + > key->ip.frag = OVS_FRAG_TYPE_NONE; > skb_clear_hash(skb); > skb->ignore_df = 1; > diff --git a/datapath/flow.c b/datapath/flow.c > index 99dae79..083288f 100644 > --- a/datapath/flow.c > +++ b/datapath/flow.c > @@ -493,79 +493,14 @@ invalid: > } > > /** > - * key_extract - extracts a flow key from an Ethernet frame. > + * key_extract_l3l4 - extracts L3/L4 header information. > * @skb: sk_buff that contains the frame, with skb->data pointing to the > - * Ethernet header > + * L3 header > * @key: output flow key > - * > - * The caller must ensure that skb->len >= ETH_HLEN. > - * > - * Returns 0 if successful, otherwise a negative errno value. > - * > - * Initializes @skb header fields as follows: > - * > - * - skb->mac_header: the L2 header. > - * > - * - skb->network_header: just past the L2 header, or just past the > - * VLAN header, to the first byte of the L2 payload. > - * > - * - skb->transport_header: If key->eth.type is ETH_P_IP or ETH_P_IPV6 > - * on output, then just past the IP header, if one is present and > - * of a correct length, otherwise the same as skb->network_header. > - * For other key->eth.type values it is left untouched. > - * > - * - skb->protocol: the type of the data starting at skb->network_header. > - * Equals to key->eth.type. > */ > -static int key_extract(struct sk_buff *skb, struct sw_flow_key *key) > +static int key_extract_l3l4(struct sk_buff *skb, struct sw_flow_key *key) > { > int error; > - struct ethhdr *eth; > - > - /* Flags are always used as part of stats */ > - key->tp.flags = 0; > - > - skb_reset_mac_header(skb); > - > - /* Link layer. */ > - clear_vlan(key); > - if (ovs_key_mac_proto(key) == MAC_PROTO_NONE) { > - if (unlikely(eth_type_vlan(skb->protocol))) > - return -EINVAL; > - > - skb_reset_network_header(skb); > - key->eth.type = skb->protocol; > - } else { > - eth = eth_hdr(skb); > - ether_addr_copy(key->eth.src, eth->h_source); > - ether_addr_copy(key->eth.dst, eth->h_dest); > - > - __skb_pull(skb, 2 * ETH_ALEN); > - /* We are going to push all headers that we pull, so no need to > - * update skb->csum here. > - */ > - > - if (unlikely(parse_vlan(skb, key))) > - return -ENOMEM; > - > - key->eth.type = parse_ethertype(skb); > - if (unlikely(key->eth.type == htons(0))) > - return -ENOMEM; > - > - /* Multiple tagged packets need to retain TPID to satisfy > - * skb_vlan_pop(), which will later shift the ethertype into > - * skb->protocol. > - */ > - if (key->eth.cvlan.tci & htons(VLAN_TAG_PRESENT)) > - skb->protocol = key->eth.cvlan.tpid; > - else > - skb->protocol = key->eth.type; > - > - skb_reset_network_header(skb); > - __skb_push(skb, skb->data - skb_mac_header(skb)); > - } > - > - skb_reset_mac_len(skb); > > /* Network layer. */ > if (key->eth.type == htons(ETH_P_IP)) { > @@ -756,6 +691,92 @@ static int key_extract(struct sk_buff *skb, struct > sw_flow_key *key) > return 0; > } > > +/** > + * key_extract - extracts a flow key from an Ethernet frame. > + * @skb: sk_buff that contains the frame, with skb->data pointing to the > + * Ethernet header > + * @key: output flow key > + * > + * The caller must ensure that skb->len >= ETH_HLEN. > + * > + * Returns 0 if successful, otherwise a negative errno value. > + * > + * Initializes @skb header fields as follows: > + * > + * - skb->mac_header: the L2 header. > + * > + * - skb->network_header: just past the L2 header, or just past the > + * VLAN header, to the first byte of the L2 payload. > + * > + * - skb->transport_header: If key->eth.type is ETH_P_IP or ETH_P_IPV6 > + * on output, then just past the IP header, if one is present and > + * of a correct length, otherwise the same as skb->network_header. > + * For other key->eth.type values it is left untouched. > + * > + * - skb->protocol: the type of the data starting at skb->network_header. > + * Equals to key->eth.type. > + */ > +static int key_extract(struct sk_buff *skb, struct sw_flow_key *key) > +{ > + struct ethhdr *eth; > + > + /* Flags are always used as part of stats */ > + key->tp.flags = 0; > + > + skb_reset_mac_header(skb); > + > + /* Link layer. */ > + clear_vlan(key); > + if (ovs_key_mac_proto(key) == MAC_PROTO_NONE) { > + if (unlikely(eth_type_vlan(skb->protocol))) > + return -EINVAL; > + > + skb_reset_network_header(skb); > + key->eth.type = skb->protocol; > + } else { > + eth = eth_hdr(skb); > + ether_addr_copy(key->eth.src, eth->h_source); > + ether_addr_copy(key->eth.dst, eth->h_dest); > + > + __skb_pull(skb, 2 * ETH_ALEN); > + /* We are going to push all headers that we pull, so no need to > + * update skb->csum here. > + */ > + > + if (unlikely(parse_vlan(skb, key))) > + return -ENOMEM; > + > + key->eth.type = parse_ethertype(skb); > + if (unlikely(key->eth.type == htons(0))) > + return -ENOMEM; > + > + /* Multiple tagged packets need to retain TPID to satisfy > + * skb_vlan_pop(), which will later shift the ethertype into > + * skb->protocol. > + */ > + if (key->eth.cvlan.tci & htons(VLAN_CFI_MASK)) > + skb->protocol = key->eth.cvlan.tpid; > + else > + skb->protocol = key->eth.type; > + > + skb_reset_network_header(skb); > + __skb_push(skb, skb->data - skb_mac_header(skb)); > + } > + > + skb_reset_mac_len(skb); > + > + /* Fill out L3/L4 key info, if any */ > + return key_extract_l3l4(skb, key); > +} > + > +/* In the case of conntrack fragment handling it expects L3 headers, > + * add a helper. > + */ > +int ovs_flow_key_update_l3l4(struct sk_buff *skb, struct sw_flow_key *key) > +{ > + return key_extract_l3l4(skb, key); > +} > + > int ovs_flow_key_update(struct sk_buff *skb, struct sw_flow_key *key) > { > int res; > diff --git a/datapath/flow.h b/datapath/flow.h > index 07af912..78edb36 100644 > --- a/datapath/flow.h > +++ b/datapath/flow.h > @@ -275,6 +275,7 @@ u64 ovs_flow_used_time(unsigned long flow_jiffies); > > /* Update the non-metadata part of the flow key using skb. */ > int ovs_flow_key_update(struct sk_buff *skb, struct sw_flow_key *key); > +int ovs_flow_key_update_l3l4(struct sk_buff *skb, struct sw_flow_key *key); > int ovs_flow_key_extract(const struct ip_tunnel_info *tun_info, > struct sk_buff *skb, > struct sw_flow_key *key); > -- > 1.8.3.1 > _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev