aboutsummaryrefslogtreecommitdiffstats
path: root/net/openvswitch
diff options
context:
space:
mode:
authorJiri Benc <jbenc@redhat.com>2016-11-10 10:28:18 -0500
committerDavid S. Miller <davem@davemloft.net>2016-11-13 00:51:02 -0500
commit329f45bc4f191c663dc156c510816411a4310578 (patch)
tree8e505cd157e30c5cbfe4789822ed4f571806d276 /net/openvswitch
parent738314a084aae5f76ff760279034b39d52c42e8b (diff)
openvswitch: add mac_proto field to the flow key
Use a hole in the structure. We support only Ethernet so far and will add a support for L2-less packets shortly. We could use a bool to indicate whether the Ethernet header is present or not but the approach with the mac_proto field is more generic and occupies the same number of bytes in the struct, while allowing later extensibility. It also makes the code in the next patches more self explaining. It would be nice to use ARPHRD_ constants but those are u16 which would be waste. Thus define our own constants. Another upside of this is that we can overload this new field to also denote whether the flow key is valid. This has the advantage that on refragmentation, we don't have to reparse the packet but can rely on the stored eth.type. This is especially important for the next patches in this series - instead of adding another branch for L2-less packets before calling ovs_fragment, we can just remove all those branches completely. Signed-off-by: Jiri Benc <jbenc@redhat.com> Acked-by: Pravin B Shelar <pshelar@ovn.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/openvswitch')
-rw-r--r--net/openvswitch/actions.c14
-rw-r--r--net/openvswitch/flow.c1
-rw-r--r--net/openvswitch/flow.h22
-rw-r--r--net/openvswitch/flow_netlink.c5
4 files changed, 31 insertions, 11 deletions
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
index 49af167105d3..44144f914920 100644
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -137,12 +137,12 @@ static struct deferred_action *add_deferred_actions(struct sk_buff *skb,
137 137
138static void invalidate_flow_key(struct sw_flow_key *key) 138static void invalidate_flow_key(struct sw_flow_key *key)
139{ 139{
140 key->eth.type = htons(0); 140 key->mac_proto |= SW_FLOW_KEY_INVALID;
141} 141}
142 142
143static bool is_flow_key_valid(const struct sw_flow_key *key) 143static bool is_flow_key_valid(const struct sw_flow_key *key)
144{ 144{
145 return !!key->eth.type; 145 return !(key->mac_proto & SW_FLOW_KEY_INVALID);
146} 146}
147 147
148static void update_ethertype(struct sk_buff *skb, struct ethhdr *hdr, 148static void update_ethertype(struct sk_buff *skb, struct ethhdr *hdr,
@@ -796,16 +796,8 @@ static void do_output(struct datapath *dp, struct sk_buff *skb, int out_port,
796 ovs_vport_send(vport, skb); 796 ovs_vport_send(vport, skb);
797 } else if (mru <= vport->dev->mtu) { 797 } else if (mru <= vport->dev->mtu) {
798 struct net *net = read_pnet(&dp->net); 798 struct net *net = read_pnet(&dp->net);
799 __be16 ethertype = key->eth.type;
800 799
801 if (!is_flow_key_valid(key)) { 800 ovs_fragment(net, vport, skb, mru, key->eth.type);
802 if (eth_p_mpls(skb->protocol))
803 ethertype = skb->inner_protocol;
804 else
805 ethertype = vlan_get_protocol(skb);
806 }
807
808 ovs_fragment(net, vport, skb, mru, ethertype);
809 } else { 801 } else {
810 kfree_skb(skb); 802 kfree_skb(skb);
811 } 803 }
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
index 22087062bd10..96c8c4716603 100644
--- a/net/openvswitch/flow.c
+++ b/net/openvswitch/flow.c
@@ -751,6 +751,7 @@ int ovs_flow_key_extract(const struct ip_tunnel_info *tun_info,
751 key->phy.skb_mark = skb->mark; 751 key->phy.skb_mark = skb->mark;
752 ovs_ct_fill_key(skb, key); 752 ovs_ct_fill_key(skb, key);
753 key->ovs_flow_hash = 0; 753 key->ovs_flow_hash = 0;
754 key->mac_proto = MAC_PROTO_ETHERNET;
754 key->recirc_id = 0; 755 key->recirc_id = 0;
755 756
756 return key_extract(skb, key); 757 return key_extract(skb, key);
diff --git a/net/openvswitch/flow.h b/net/openvswitch/flow.h
index ae783f5c6695..f61cae7f9030 100644
--- a/net/openvswitch/flow.h
+++ b/net/openvswitch/flow.h
@@ -37,6 +37,12 @@
37 37
38struct sk_buff; 38struct sk_buff;
39 39
40enum sw_flow_mac_proto {
41 MAC_PROTO_NONE = 0,
42 MAC_PROTO_ETHERNET,
43};
44#define SW_FLOW_KEY_INVALID 0x80
45
40/* Store options at the end of the array if they are less than the 46/* Store options at the end of the array if they are less than the
41 * maximum size. This allows us to get the benefits of variable length 47 * maximum size. This allows us to get the benefits of variable length
42 * matching for small options. 48 * matching for small options.
@@ -68,6 +74,7 @@ struct sw_flow_key {
68 u32 skb_mark; /* SKB mark. */ 74 u32 skb_mark; /* SKB mark. */
69 u16 in_port; /* Input switch port (or DP_MAX_PORTS). */ 75 u16 in_port; /* Input switch port (or DP_MAX_PORTS). */
70 } __packed phy; /* Safe when right after 'tun_key'. */ 76 } __packed phy; /* Safe when right after 'tun_key'. */
77 u8 mac_proto; /* MAC layer protocol (e.g. Ethernet). */
71 u8 tun_proto; /* Protocol of encapsulating tunnel. */ 78 u8 tun_proto; /* Protocol of encapsulating tunnel. */
72 u32 ovs_flow_hash; /* Datapath computed hash value. */ 79 u32 ovs_flow_hash; /* Datapath computed hash value. */
73 u32 recirc_id; /* Recirculation ID. */ 80 u32 recirc_id; /* Recirculation ID. */
@@ -206,6 +213,21 @@ struct arp_eth_header {
206 unsigned char ar_tip[4]; /* target IP address */ 213 unsigned char ar_tip[4]; /* target IP address */
207} __packed; 214} __packed;
208 215
216static inline u8 ovs_key_mac_proto(const struct sw_flow_key *key)
217{
218 return key->mac_proto & ~SW_FLOW_KEY_INVALID;
219}
220
221static inline u16 __ovs_mac_header_len(u8 mac_proto)
222{
223 return mac_proto == MAC_PROTO_ETHERNET ? ETH_HLEN : 0;
224}
225
226static inline u16 ovs_mac_header_len(const struct sw_flow_key *key)
227{
228 return __ovs_mac_header_len(ovs_key_mac_proto(key));
229}
230
209static inline bool ovs_identifier_is_ufid(const struct sw_flow_id *sfid) 231static inline bool ovs_identifier_is_ufid(const struct sw_flow_id *sfid)
210{ 232{
211 return sfid->ufid_len; 233 return sfid->ufid_len;
diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c
index ae25ded82b3b..ccb9900c5230 100644
--- a/net/openvswitch/flow_netlink.c
+++ b/net/openvswitch/flow_netlink.c
@@ -1059,6 +1059,11 @@ static int metadata_from_nlattrs(struct net *net, struct sw_flow_match *match,
1059 sizeof(*cl), is_mask); 1059 sizeof(*cl), is_mask);
1060 *attrs &= ~(1ULL << OVS_KEY_ATTR_CT_LABELS); 1060 *attrs &= ~(1ULL << OVS_KEY_ATTR_CT_LABELS);
1061 } 1061 }
1062
1063 /* Always exact match mac_proto */
1064 SW_FLOW_KEY_PUT(match, mac_proto, is_mask ? 0xff : MAC_PROTO_ETHERNET,
1065 is_mask);
1066
1062 return 0; 1067 return 0;
1063} 1068}
1064 1069