On Thu, Jun 9, 2016 at 4:57 PM, William Tu <u9012...@gmail.com> wrote: > 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 <u9012...@gmail.com> > --- > v1 -> v2: > - Use 32 bits cutlen and fix unnecessary cutlen initilization. > - Fix cutlen leaks to remaining actions under sample action. > - In queue_userspace_packet, don't extract hlen when using skb_zerocopy. > --- > include/uapi/linux/openvswitch.h | 7 +++++++ > net/openvswitch/actions.c | 34 ++++++++++++++++++++++++++++++---- > net/openvswitch/datapath.c | 27 ++++++++++++++++----------- > net/openvswitch/datapath.h | 5 ++++- > net/openvswitch/flow_netlink.c | 9 +++++++++ > net/openvswitch/vport.c | 1 + > 6 files changed, 67 insertions(+), 16 deletions(-)
... ... > diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c > index 9a3eb7a..64dbc80 100644 > --- a/net/openvswitch/actions.c > +++ b/net/openvswitch/actions.c > @@ -750,6 +750,10 @@ static void do_output(struct datapath *dp, struct > sk_buff *skb, int out_port, > > if (likely(vport)) { > u16 mru = OVS_CB(skb)->mru; > + u32 cutlen = OVS_CB(skb)->cutlen; > + > + if (cutlen > 0) > + pskb_trim(skb, skb->len - cutlen); > Lets add check min packet length. also add unlikely annotation to the condition. > if (likely(!mru || (skb->len <= mru + ETH_HLEN))) { > ovs_vport_send(vport, skb); ... ... > @@ -1059,8 +1077,16 @@ static int do_execute_actions(struct datapath *dp, > struct sk_buff *skb, > prev_port = nla_get_u32(a); > break; > > + case OVS_ACTION_ATTR_TRUNC: { > + struct ovs_action_trunc *trunc = nla_data(a); > + > + if (skb->len > trunc->max_len) > + OVS_CB(skb)->cutlen = skb->len - > trunc->max_len; > + break; > + } > + > case OVS_ACTION_ATTR_USERSPACE: > - output_userspace(dp, skb, key, a, attr, len); > + output_userspace(dp, skb, key, a, attr, len, 0); Need to pass cutlen here to truncate packet for userspace action. Also reset cutlen to zero for the skb after this action is executed. > break; > > case OVS_ACTION_ATTR_HASH: > diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c > index 856bd8d..26f947e 100644 > --- a/net/openvswitch/datapath.c > +++ b/net/openvswitch/datapath.c ... ... > > 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; > @@ -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; If packet is truncated there is no need to allocate buffer according to full packet packet length.