On Tue, Oct 03, 2017 at 03:13:08AM +0800, Jiri Benc wrote:
> On Fri, 29 Sep 2017 15:03:30 +0800, Yi Yang wrote:
> > --- a/include/net/nsh.h
> > +++ b/include/net/nsh.h
> > @@ -304,4 +304,7 @@ static inline void nsh_set_flags_ttl_len(struct nshhdr 
> > *nsh, u8 flags,
> >                     NSH_FLAGS_MASK | NSH_TTL_MASK | NSH_LEN_MASK);
> >  }
> >  
> > +int skb_push_nsh(struct sk_buff *skb, const struct nshhdr *nh);
> 
> [...]
> > +int skb_push_nsh(struct sk_buff *skb, const struct nshhdr *src_nsh_hdr)
> 
> This is minor but since this patch will need a respin anyway, please
> name the variables in the forward declaration and here the same.

Sorry for late reply, I was taking vacation from Oct. 1 to Oct. 8. I will
change "nh" and "src_nsh_hdr" to "pushed_nsh" because there is
another nh inside of skb_push_nsh.

> 
> > +int skb_pop_nsh(struct sk_buff *skb)
> > +{
> > +   int err;
> > +   struct nshhdr *nsh_hdr = (struct nshhdr *)(skb->data);
> 
> Bad name of the variable, clashes with the nsh_hdr function. I pointed
> that out already.

Sorry for missing this, I just did change in one .c file, forgot to do
the same thing in other .c files.

> 
> > +   size_t length;
> > +   __be16 inner_proto;
> > +
> > +   err = skb_ensure_writable(skb, skb_network_offset(skb) +
> > +                                  sizeof(struct nshhdr));
> 
> You assume that the skb starts at the NSH header, thus the
> skb_network_offset is completely unnecessary and introduces just
> another assumption on the caller. Also, the sizeof(struct nshhdr) is
> wrong: there's no guarantee that the header is not smaller or larger
> than that.
> 
> More importantly though, why do you need skb_ensure_writable? You don't
> write into the header. pkskb_may_pull is enough.
> 
>       if (!pskb_may_pull(skb, NSH_BASE_HDR_LEN))
>               return -ENOMEM;
>       length = nsh_hdr_len(nsh_hdr);
>       if (!pskb_may_pull(skb, length))
>               return -ENOMEM;
> 

Thank you for pointing out this, your version is the best one.

> > +static int set_nsh(struct sk_buff *skb, struct sw_flow_key *flow_key,
> > +              const struct nlattr *a)
> > +{
> > +   struct nshhdr *nh;
> > +   int err;
> > +   u8 flags;
> > +   u8 ttl;
> > +   int i;
> > +
> > +   struct ovs_key_nsh key;
> > +   struct ovs_key_nsh mask;
> > +
> > +   err = nsh_key_from_nlattr(a, &key, &mask);
> > +   if (err)
> > +           return err;
> > +
> > +   err = skb_ensure_writable(skb, skb_network_offset(skb) +
> > +                                  sizeof(struct nshhdr));
> 
> I missed this before: this is wrong, too. You need to use the real
> header size, not sizeof(struct nshhdr). It should be computable from
> the flow key.

It will be better to use code you provided above.

> 
> > +           case OVS_ACTION_ATTR_PUSH_NSH: {
> > +                   u8 buffer[NSH_HDR_MAX_LEN];
> > +                   struct nshhdr *nh = (struct nshhdr *)buffer;
> > +
> > +                   nsh_hdr_from_nlattr(nla_data(a), nh,
> > +                                       NSH_HDR_MAX_LEN);
> > +                   err = push_nsh(skb, key, (const struct nshhdr *)nh);
> 
> Is the cast to const really needed? It looks suspicious. If you added it
> because a compiler complained, it's even more suspicious.

You're right, it is ok after I remove "(const struct nshhdr *)".

> 
> > +static int parse_nsh(struct sk_buff *skb, struct sw_flow_key *key)
> > +{
> > +   struct nshhdr *nh;
> > +   unsigned int nh_ofs = skb_network_offset(skb);
> > +   u8 version, length;
> > +   int err;
> > +
> > +   err = check_header(skb, nh_ofs + NSH_BASE_HDR_LEN);
> > +   if (unlikely(err))
> > +           return err;
> > +
> > +   nh = nsh_hdr(skb);
> > +   version = nsh_get_ver(nh);
> > +   length = nsh_hdr_len(nh);
> > +
> > +   if (version != 0)
> > +           return -EINVAL;
> > +
> > +   err = check_header(skb, nh_ofs + length);
> > +   if (unlikely(err))
> > +           return err;
> > +
> > +   nh = (struct nshhdr *)skb_network_header(skb);
> 
> I really really really hate this. This is the third time I'm telling
> you to use the nsh_hdr function. Every time, you change only part of
> the places. And this one I even explicitly pointed out in the previous
> review.
> 
> I'm not supposed to look at my previous review to verify that you
> addressed everything. That's your responsibility. Yet I need to do it
> because every time, some of my comments remain unaddressed.

Sorry, it is a missing change, accumulated comments overwhelmed this.

> 
> > +int nsh_hdr_from_nlattr(const struct nlattr *attr,
> > +                   struct nshhdr *nh, size_t size)
> > +{
> > +   struct nlattr *a;
> > +   int rem;
> > +   u8 flags = 0;
> > +   u8 ttl = 0;
> > +   int mdlen = 0;
> > +
> > +   /* validate_nsh has check this, so we needn't do duplicate check here
> > +    */
> > +   nla_for_each_nested(a, attr, rem) {
> > +           int type = nla_type(a);
> > +
> > +           switch (type) {
> > +           case OVS_NSH_KEY_ATTR_BASE: {
> > +                   const struct ovs_nsh_key_base *base = nla_data(a);
> > +
> > +                   flags = base->flags;
> > +                   ttl = base->ttl;
> > +                   nh->np = base->np;
> > +                   nh->mdtype = base->mdtype;
> > +                   nh->path_hdr = base->path_hdr;
> > +                   break;
> > +           }
> > +           case OVS_NSH_KEY_ATTR_MD1: {
> > +                   const struct ovs_nsh_key_md1 *md1 = nla_data(a);
> > +
> > +                   mdlen = nla_len(a);
> > +                   memcpy(&nh->md1, md1, mdlen);
> > +                   break;
> 
> Looks better. Why not simplify it even more?
> 
>               case OVS_NSH_KEY_ATTR_MD1:
>                       mdlen = nla_len(a);
>                       memcpy(&nh->md1, nla_data(a), mdlen);
>                       break;
> 
> It's still perfectly readable this way and there's no need for the
> braces.

> 
> > +           }
> > +           case OVS_NSH_KEY_ATTR_MD2: {
> > +                   const struct u8 *md2 = nla_data(a);
> > +
> > +                   mdlen = nla_len(a);
> > +                   memcpy(&nh->md2, md2, mdlen);
> 
> And here, too.

Yes, the code you provided is better.

> 
> > +int nsh_key_from_nlattr(const struct nlattr *attr,
> > +                   struct ovs_key_nsh *nsh, struct ovs_key_nsh *nsh_mask)
> > +{
> > +   struct nlattr *a;
> > +   int rem;
> > +
> > +   /* validate_nsh has check this, so we needn't do duplicate check here
> > +    */
> > +   nla_for_each_nested(a, attr, rem) {
> > +           int type = nla_type(a);
> > +
> > +           switch (type) {
> > +           case OVS_NSH_KEY_ATTR_BASE: {
> > +                   const struct ovs_nsh_key_base *base = nla_data(a);
> > +                   const struct ovs_nsh_key_base *base_mask = base + 1;
> > +
> > +                   nsh->base = *base;
> > +                   nsh_mask->base = *base_mask;
> > +                   break;
> > +           }
> > +           case OVS_NSH_KEY_ATTR_MD1: {
> > +                   const struct ovs_nsh_key_md1 *md1 =
> > +                           (struct ovs_nsh_key_md1 *)nla_data(a);
> 
> I'm speechless.
> 
> Yes, I don't like the line above. For a reason that I already pointed
> out.
> 
> I expected more of this version.

Sorry, these are also missing changes, I remember I did global change
about this comment, it is my bad.

Here is incremental patch against v11, I'll send out v12 if you haven't
more comments about this.

diff -u b/include/net/nsh.h b/include/net/nsh.h
--- b/include/net/nsh.h
+++ b/include/net/nsh.h
@@ -304,7 +304,7 @@
                        NSH_FLAGS_MASK | NSH_TTL_MASK | NSH_LEN_MASK);
 }
 
-int skb_push_nsh(struct sk_buff *skb, const struct nshhdr *nh);
+int skb_push_nsh(struct sk_buff *skb, const struct nshhdr *pushed_nh);
 int skb_pop_nsh(struct sk_buff *skb);
 
 #endif /* __NET_NSH_H */
diff -u b/net/nsh/nsh.c b/net/nsh/nsh.c
--- b/net/nsh/nsh.c
+++ b/net/nsh/nsh.c
@@ -14,10 +14,10 @@
 #include <net/nsh.h>
 #include <net/tun_proto.h>
 
-int skb_push_nsh(struct sk_buff *skb, const struct nshhdr *src_nsh_hdr)
+int skb_push_nsh(struct sk_buff *skb, const struct nshhdr *pushed_nh)
 {
-       struct nshhdr *nsh_hdr;
-       size_t length = nsh_hdr_len(src_nsh_hdr);
+       struct nshhdr *nh;
+       size_t length = nsh_hdr_len(pushed_nh);
        u8 next_proto;
 
        if (skb->mac_len) {
@@ -33,9 +33,9 @@
                return -ENOMEM;
 
        skb_push(skb, length);
-       nsh_hdr = (struct nshhdr *)(skb->data);
-       memcpy(nsh_hdr, src_nsh_hdr, length);
-       nsh_hdr->np = next_proto;
+       nh = (struct nshhdr *)(skb->data);
+       memcpy(nh, pushed_nh, length);
+       nh->np = next_proto;
 
        skb->protocol = htons(ETH_P_NSH);
        skb_reset_mac_header(skb);
@@ -48,21 +48,23 @@
 
 int skb_pop_nsh(struct sk_buff *skb)
 {
-       int err;
-       struct nshhdr *nsh_hdr = (struct nshhdr *)(skb->data);
+       struct nshhdr *nh;
        size_t length;
        __be16 inner_proto;
 
-       err = skb_ensure_writable(skb, skb_network_offset(skb) +
-                                      sizeof(struct nshhdr));
-       if (unlikely(err))
-               return err;
+       if (!pskb_may_pull(skb, NSH_BASE_HDR_LEN))
+               return -ENOMEM;
+       nh = (struct nshhdr *)(skb->data);
+       length = nsh_hdr_len(nh);
+       if (!pskb_may_pull(skb, length))
+               return -ENOMEM;
 
-       inner_proto = tun_p_to_eth_p(nsh_hdr->np);
+       nh = (struct nshhdr *)(skb->data);
+       inner_proto = tun_p_to_eth_p(nh->np);
        if (!inner_proto)
                return -EAFNOSUPPORT;
 
-       length = nsh_hdr_len(nsh_hdr);
+       length = nsh_hdr_len(nh);
        skb_pull(skb, length);
        skb_reset_mac_header(skb);
        skb_reset_network_header(skb);
diff -u b/net/openvswitch/actions.c b/net/openvswitch/actions.c
--- b/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -644,6 +644,7 @@
                   const struct nlattr *a)
 {
        struct nshhdr *nh;
+       size_t length;
        int err;
        u8 flags;
        u8 ttl;
@@ -656,13 +657,22 @@
        if (err)
                return err;
 
+       /* Make sure the NSH base header is there */
        err = skb_ensure_writable(skb, skb_network_offset(skb) +
-                                      sizeof(struct nshhdr));
+                                      NSH_BASE_HDR_LEN);
        if (unlikely(err))
                return err;
 
        nh = nsh_hdr(skb);
+       length = nsh_hdr_len(nh);
 
+       /* Make sure the whole NSH header is there */
+       err = skb_ensure_writable(skb, skb_network_offset(skb) +
+                                      length);
+       if (unlikely(err))
+               return err;
+
+       nh = nsh_hdr(skb);
        flags = nsh_get_flags(nh);
        flags = OVS_MASKED(flags, key.base.flags, mask.base.flags);
        flow_key->nsh.base.flags = flags;
@@ -1312,7 +1322,7 @@
 
                        nsh_hdr_from_nlattr(nla_data(a), nh,
                                            NSH_HDR_MAX_LEN);
-                       err = push_nsh(skb, key, (const struct nshhdr *)nh);
+                       err = push_nsh(skb, key, nh);
                        break;
                }
 
diff -u b/net/openvswitch/flow.c b/net/openvswitch/flow.c
--- b/net/openvswitch/flow.c
+++ b/net/openvswitch/flow.c
@@ -513,7 +513,7 @@
        if (unlikely(err))
                return err;
 
-       nh = (struct nshhdr *)skb_network_header(skb);
+       nh = nsh_hdr(skb);
        key->nsh.base.flags = nsh_get_flags(nh);
        key->nsh.base.ttl = nsh_get_ttl(nh);
        key->nsh.base.mdtype = nh->mdtype;
diff -u b/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c
--- b/net/openvswitch/flow_netlink.c
+++ b/net/openvswitch/flow_netlink.c
@@ -1233,20 +1233,16 @@
                        nh->path_hdr = base->path_hdr;
                        break;
                }
-               case OVS_NSH_KEY_ATTR_MD1: {
-                       const struct ovs_nsh_key_md1 *md1 = nla_data(a);
-
+               case OVS_NSH_KEY_ATTR_MD1:
                        mdlen = nla_len(a);
-                       memcpy(&nh->md1, md1, mdlen);
+                       memcpy(&nh->md1, nla_data(a), mdlen);
                        break;
-               }
-               case OVS_NSH_KEY_ATTR_MD2: {
-                       const struct u8 *md2 = nla_data(a);
 
+               case OVS_NSH_KEY_ATTR_MD2:
                        mdlen = nla_len(a);
-                       memcpy(&nh->md2, md2, mdlen);
+                       memcpy(&nh->md2, nla_data(a), mdlen);
                        break;
-               }
+
                default:
                        return -EINVAL;
                }
@@ -1280,8 +1276,7 @@
                        break;
                }
                case OVS_NSH_KEY_ATTR_MD1: {
-                       const struct ovs_nsh_key_md1 *md1 =
-                               (struct ovs_nsh_key_md1 *)nla_data(a);
+                       const struct ovs_nsh_key_md1 *md1 = nla_data(a);
                        const struct ovs_nsh_key_md1 *md1_mask = md1 + 1;
 
                        memcpy(nsh->context, md1->context, sizeof(*md1));
@@ -1339,8 +1334,7 @@
 
                switch (type) {
                case OVS_NSH_KEY_ATTR_BASE: {
-                       const struct ovs_nsh_key_base *base =
-                               (struct ovs_nsh_key_base *)nla_data(a);
+                       const struct ovs_nsh_key_base *base = nla_data(a);
 
                        has_base = true;
                        mdtype = base->mdtype;
@@ -1357,8 +1351,7 @@
                        break;
                }
                case OVS_NSH_KEY_ATTR_MD1: {
-                       const struct ovs_nsh_key_md1 *md1 =
-                               (struct ovs_nsh_key_md1 *)nla_data(a);
+                       const struct ovs_nsh_key_md1 *md1 = nla_data(a);
 
                        has_md1 = true;
                        for (i = 0; i < NSH_MD1_CONTEXT_SIZE; i++)

Reply via email to