diff options
author | William Tu <u9012063@gmail.com> | 2016-06-10 20:49:33 +0200 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-06-11 02:58:03 +0200 |
commit | f2a4d086ed4c588d32fe9b7aa67fead7280e7bf1 (patch) | |
tree | 7824d6446b4fd259cc7430641fd27475445361ba /net/openvswitch/datapath.c | |
parent | Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net (diff) | |
download | linux-f2a4d086ed4c588d32fe9b7aa67fead7280e7bf1.tar.xz linux-f2a4d086ed4c588d32fe9b7aa67fead7280e7bf1.zip |
openvswitch: Add packet truncation support.
The patch adds a new OVS action, OVS_ACTION_ATTR_TRUNC, in order to
truncate packets. A 'max_len' is added for setting up the maximum
packet size, and a 'cutlen' field is to record the number of bytes
to trim the packet when the packet is outputting to a port, or when
the packet is sent to userspace.
Signed-off-by: William Tu <u9012063@gmail.com>
Cc: Pravin Shelar <pshelar@nicira.com>
Acked-by: Pravin B Shelar <pshelar@ovn.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/openvswitch/datapath.c')
-rw-r--r-- | net/openvswitch/datapath.c | 29 |
1 files changed, 17 insertions, 12 deletions
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index 856bd8dba676..673934295333 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c @@ -137,10 +137,12 @@ EXPORT_SYMBOL_GPL(lockdep_ovsl_is_held); static struct vport *new_vport(const struct vport_parms *); static int queue_gso_packets(struct datapath *dp, struct sk_buff *, const struct sw_flow_key *, - const struct dp_upcall_info *); + const struct dp_upcall_info *, + uint32_t cutlen); static int queue_userspace_packet(struct datapath *dp, struct sk_buff *, const struct sw_flow_key *, - const struct dp_upcall_info *); + const struct dp_upcall_info *, + uint32_t cutlen); /* Must be called with rcu_read_lock. */ static struct datapath *get_dp_rcu(struct net *net, int dp_ifindex) @@ -275,7 +277,7 @@ void ovs_dp_process_packet(struct sk_buff *skb, struct sw_flow_key *key) upcall.cmd = OVS_PACKET_CMD_MISS; upcall.portid = ovs_vport_find_upcall_portid(p, skb); upcall.mru = OVS_CB(skb)->mru; - error = ovs_dp_upcall(dp, skb, key, &upcall); + error = ovs_dp_upcall(dp, skb, key, &upcall, 0); if (unlikely(error)) kfree_skb(skb); else @@ -300,7 +302,8 @@ out: int ovs_dp_upcall(struct datapath *dp, struct sk_buff *skb, const struct sw_flow_key *key, - const struct dp_upcall_info *upcall_info) + const struct dp_upcall_info *upcall_info, + uint32_t cutlen) { struct dp_stats_percpu *stats; int err; @@ -311,9 +314,9 @@ int ovs_dp_upcall(struct datapath *dp, struct sk_buff *skb, } if (!skb_is_gso(skb)) - err = queue_userspace_packet(dp, skb, key, upcall_info); + err = queue_userspace_packet(dp, skb, key, upcall_info, cutlen); else - err = queue_gso_packets(dp, skb, key, upcall_info); + err = queue_gso_packets(dp, skb, key, upcall_info, cutlen); if (err) goto err; @@ -331,7 +334,8 @@ err: static int queue_gso_packets(struct datapath *dp, struct sk_buff *skb, const struct sw_flow_key *key, - const struct dp_upcall_info *upcall_info) + const struct dp_upcall_info *upcall_info, + uint32_t cutlen) { unsigned short gso_type = skb_shinfo(skb)->gso_type; struct sw_flow_key later_key; @@ -360,7 +364,7 @@ static int queue_gso_packets(struct datapath *dp, struct sk_buff *skb, if (gso_type & SKB_GSO_UDP && skb != segs) key = &later_key; - err = queue_userspace_packet(dp, skb, key, upcall_info); + err = queue_userspace_packet(dp, skb, key, upcall_info, cutlen); if (err) break; @@ -416,7 +420,8 @@ static void pad_packet(struct datapath *dp, struct sk_buff *skb) static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb, const struct sw_flow_key *key, - const struct dp_upcall_info *upcall_info) + const struct dp_upcall_info *upcall_info, + uint32_t cutlen) { struct ovs_header *upcall; struct sk_buff *nskb = NULL; @@ -461,7 +466,7 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb, else hlen = skb->len; - len = upcall_msg_size(upcall_info, hlen); + len = upcall_msg_size(upcall_info, hlen - cutlen); user_skb = genlmsg_new(len, GFP_ATOMIC); if (!user_skb) { err = -ENOMEM; @@ -515,9 +520,9 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb, err = -ENOBUFS; goto out; } - nla->nla_len = nla_attr_size(skb->len); + nla->nla_len = nla_attr_size(skb->len - cutlen); - err = skb_zerocopy(user_skb, skb, skb->len, hlen); + err = skb_zerocopy(user_skb, skb, skb->len - cutlen, hlen); if (err) goto out; |