Hi Andy,

I think your plan to remove ambiguity is a good one.

On Tue, Jul 30, 2013 at 09:09:35PM -0700, Andy Zhou wrote:
> Simon, Thanks for the review.
> The intention of my patch is to always export those attributes to remove
> the ambiguity associated with interpreting missing attributes. Glad to hear
> this patch would work well with recirculation.
> 
> 
> On Tue, Jul 30, 2013 at 8:54 PM, Simon Horman <ho...@verge.net.au> wrote:
> 
> > On Tue, Jul 30, 2013 at 07:49:13PM -0700, Andy Zhou wrote:
> > > Handling of missing attributes in netlink can be tricky and turns out
> > > to be error prone. The value (savings in netlink bandwidth) does not
> > > seem to be significant enough to justify allowing them. This patch
> > > series make both kernel and userspace always export priority and
> > > skb_mark attribute. There will be follow on patches in the
> > > direction of making all attributes explicit.
> > >
> > > Signed-off-by: Andy Zhou <az...@nicira.com>
> > > ---
> > >  lib/odp-util.c        |   62
> > +++++++++++++++++++++++++++++++++++++++----------
> > >  tests/ofproto-dpif.at |   18 +++++++-------
> > >  2 files changed, 59 insertions(+), 21 deletions(-)
> > >
> > > diff --git a/lib/odp-util.c b/lib/odp-util.c
> > > index 3c3063d..1f7db2f 100644
> > > --- a/lib/odp-util.c
> > > +++ b/lib/odp-util.c
> > > @@ -926,6 +926,42 @@ odp_mask_attr_is_exact(const struct nlattr *ma)
> > >      return is_exact;
> > >  }
> > >
> > > +static bool
> > > +ommit_format(enum ovs_key_attr attr, const struct nlattr *a,
> > > +             const struct nlattr *ma)
> > > +{
> > > +    switch (attr) {
> > > +        case OVS_KEY_ATTR_PRIORITY:
> > > +        case OVS_KEY_ATTR_SKB_MARK:
> > > +            if (!nl_attr_get_u32(a)) {
> > > +                if ((!ma) || !nl_attr_get_u32(ma)) {
> > > +                    return true;  /* Omit output 0 (no mask) or 0/0  */
> > > +                }
> > > +            }
> > > +            break;
> > > +        case OVS_KEY_ATTR_UNSPEC:
> > > +        case OVS_KEY_ATTR_ENCAP:
> > > +        case OVS_KEY_ATTR_TUNNEL:
> > > +        case OVS_KEY_ATTR_IN_PORT:
> > > +        case OVS_KEY_ATTR_ETHERNET:
> > > +        case OVS_KEY_ATTR_VLAN:
> > > +        case OVS_KEY_ATTR_ETHERTYPE:
> > > +        case OVS_KEY_ATTR_IPV4:
> > > +        case OVS_KEY_ATTR_IPV6:
> > > +        case OVS_KEY_ATTR_TCP:
> > > +        case OVS_KEY_ATTR_UDP:
> > > +        case OVS_KEY_ATTR_ICMP:
> > > +        case OVS_KEY_ATTR_ICMPV6:
> > > +        case OVS_KEY_ATTR_ARP:
> > > +        case OVS_KEY_ATTR_ND:
> > > +        case OVS_KEY_ATTR_MPLS:
> > > +        case __OVS_KEY_ATTR_MAX:
> > > +        default:
> > > +            break;
> > > +    }
> > > +
> > > +    return false;
> > > +}
> > >
> > >  static void
> > >  format_odp_key_attr(const struct nlattr *a, const struct nlattr *ma,
> > > @@ -1345,13 +1381,13 @@ odp_flow_format(const struct nlattr *key, size_t
> > key_len,
> > >          bool has_ethtype_key = false;
> > >          const struct nlattr *ma = NULL;
> > >          struct ofpbuf ofp;
> > > +        bool first_key = true;
> > >
> > >          ofpbuf_init(&ofp, 100);
> > >          NL_ATTR_FOR_EACH (a, left, key, key_len) {
> > > -            if (a != key) {
> > > -                ds_put_char(ds, ',');
> > > -            }
> > > -            if (nl_attr_type(a) == OVS_KEY_ATTR_ETHERTYPE) {
> > > +            enum ovs_key_attr attr = nl_attr_type(a);
> > > +
> > > +            if ( attr == OVS_KEY_ATTR_ETHERTYPE) {
> > >                  has_ethtype_key = true;
> > >              }
> > >              if (mask && mask_len) {
> > > @@ -1360,8 +1396,14 @@ odp_flow_format(const struct nlattr *key, size_t
> > key_len,
> > >                      ma = generate_all_wildcard_mask(&ofp, a);
> > >                  }
> > >              }
> > > -            format_odp_key_attr(a, ma, ds);
> > > -            ofpbuf_clear(&ofp);
> > > +            if (!ommit_format(attr, a, ma)) {
> > > +                if (!first_key) {
> > > +                    ds_put_char(ds, ',');
> > > +                }
> > > +                format_odp_key_attr(a, ma, ds);
> > > +                first_key = false;
> > > +                ofpbuf_clear(&ofp);
> > > +            }
> > >          }
> > >          ofpbuf_uninit(&ofp);
> > >
> > > @@ -2323,17 +2365,13 @@ odp_flow_key_from_flow__(struct ofpbuf *buf,
> > const struct flow *data,
> > >       * treat 'data' as a mask. */
> > >      is_mask = (data != flow);
> > >
> > > -    if (flow->skb_priority) {
> > > -        nl_msg_put_u32(buf, OVS_KEY_ATTR_PRIORITY, data->skb_priority);
> > > -    }
> > > +    nl_msg_put_u32(buf, OVS_KEY_ATTR_PRIORITY, data->skb_priority);
> > >
> > >      if (flow->tunnel.ip_dst) {
> > >          tun_key_to_attr(buf, &data->tunnel);
> > >      }
> > >
> > > -    if (flow->skb_mark) {
> > > -        nl_msg_put_u32(buf, OVS_KEY_ATTR_SKB_MARK, data->skb_mark);
> > > -    }
> > > +    nl_msg_put_u32(buf, OVS_KEY_ATTR_SKB_MARK, data->skb_mark);
> >
> > I came across the skb_mark portion of this problem while re-basing
> > the recirculation patches. The approach that I took in
> > included in "Add packet recirculation" v14 is as follows:
> >
> >
> >     if (flow->skb_mark || data->skb_mark) {
> >         nl_msg_put_u32(buf, OVS_KEY_ATTR_SKB_MARK, data->skb_mark);
> >     }
> >
> > This seemed to ensure that the mark was present in all cases
> > that it is needed by recirculation without adding it otherwise.
> > This avoided needing to update the test-suite. However, I think
> > your more general approach is cleaner, easier to understand,
> > and should work with recirculation: it suffers if skb_mark is not
> > present if needed but I don't believe the converse is true.
> >
> > Reviewed-by: Simon Horman <ho...@verge.net.au>
> >
> > >      /* Add an ingress port attribute if this is a mask or 'odp_in_port'
> > >       * is not the magical value "ODPP_NONE". */
> > > diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at
> > > index 2728a28..3600fb6 100644
> > > --- a/tests/ofproto-dpif.at
> > > +++ b/tests/ofproto-dpif.at
> > > @@ -2088,12 +2088,12 @@ AT_CHECK([ovs-appctl netdev-dummy/receive p2
> > 'in_port(2),eth(src=50:54:00:00:00:
> > >  AT_CHECK([ovs-appctl netdev-dummy/receive p3
> > 'in_port(3),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.0.0.2,dst=10.0.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'])
> > >
> > >  AT_CHECK([ovs-appctl dpif/dump-flows br0 | sort | STRIP_USED], [0], [dnl
> > >
> > -in_port(1),eth(src=50:54:00:00:00:05/00:00:00:00:00:00,dst=50:54:00:00:00:07/00:00:00:00:00:00),eth_type(0x0800),ipv4(src=
> > 192.168.0.1/0.0.0.0,dst=192.168.0.2/0.0.0.0,proto=1/0,tos=0/0,ttl=64/0,frag=no/0x2),icmp(type=8/0,code=0/0),
> > packets:0, bytes:0, used:0.0s,
> > actions:userspace(pid=0,slow_path(controller))
> > >
> > -in_port(2),eth(src=50:54:00:00:00:07/00:00:00:00:00:00,dst=50:54:00:00:00:05/00:00:00:00:00:00),eth_type(0x0800),ipv4(src=
> > 192.168.0.2/0.0.0.0,dst=192.168.0.1/0.0.0.0,proto=1/0,tos=0/0,ttl=64/0,frag=no/0x2),icmp(type=0/0,code=0/0),
> > packets:0, bytes:0, used:0.0s,
> > actions:userspace(pid=0,slow_path(controller))
> > >
> > +skb_priority(0),in_port(1),eth(src=50:54:00:00:00:05/00:00:00:00:00:00,dst=50:54:00:00:00:07/00:00:00:00:00:00),eth_type(0x0800),ipv4(src=
> > 192.168.0.1/0.0.0.0,dst=192.168.0.2/0.0.0.0,proto=1/0,tos=0/0,ttl=64/0,frag=no/0x2),icmp(type=8/0,code=0/0),
> > packets:0, bytes:0, used:0.0s,
> > actions:userspace(pid=0,slow_path(controller))
> > >
> > +skb_priority(0),in_port(2),eth(src=50:54:00:00:00:07/00:00:00:00:00:00,dst=50:54:00:00:00:05/00:00:00:00:00:00),eth_type(0x0800),ipv4(src=
> > 192.168.0.2/0.0.0.0,dst=192.168.0.1/0.0.0.0,proto=1/0,tos=0/0,ttl=64/0,frag=no/0x2),icmp(type=0/0,code=0/0),
> > packets:0, bytes:0, used:0.0s,
> > actions:userspace(pid=0,slow_path(controller))
> > >  ])
> > >
> > >  AT_CHECK([ovs-appctl dpif/dump-flows br1 | sort | STRIP_USED], [0], [dnl
> > >
> > -in_port(3),eth(src=50:54:00:00:00:09/00:00:00:00:00:00,dst=50:54:00:00:00:0a/00:00:00:00:00:00),eth_type(0x0800),ipv4(src=
> > 10.0.0.2/0.0.0.0,dst=10.0.0.1/0.0.0.0,proto=1/0,tos=0/0,ttl=64/0,frag=no/0x2),icmp(type=8/0,code=0/0),
> > packets:0, bytes:0, used:0.0s,
> > actions:userspace(pid=0,slow_path(controller))
> > >
> > +skb_priority(0),in_port(3),eth(src=50:54:00:00:00:09/00:00:00:00:00:00,dst=50:54:00:00:00:0a/00:00:00:00:00:00),eth_type(0x0800),ipv4(src=
> > 10.0.0.2/0.0.0.0,dst=10.0.0.1/0.0.0.0,proto=1/0,tos=0/0,ttl=64/0,frag=no/0x2),icmp(type=8/0,code=0/0),
> > packets:0, bytes:0, used:0.0s,
> > actions:userspace(pid=0,slow_path(controller))
> > >  ])
> > >
> > >  OVS_VSWITCHD_STOP
> > > @@ -2110,12 +2110,12 @@ AT_CHECK([ovs-appctl netdev-dummy/receive p2
> > 'in_port(2),eth(src=50:54:00:00:00:
> > >  AT_CHECK([ovs-appctl netdev-dummy/receive p3
> > 'in_port(3),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.0.0.2,dst=10.0.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'])
> > >
> > >  AT_CHECK([ovs-appctl dpif/dump-flows br0 | sort | STRIP_USED], [0], [dnl
> > >
> > -in_port(1),eth(src=50:54:00:00:00:05/00:00:00:00:00:00,dst=50:54:00:00:00:07/00:00:00:00:00:00),eth_type(0x0800),ipv4(src=
> > 192.168.0.1/0.0.0.0,dst=192.168.0.2/0.0.0.0,proto=1/0,tos=0/0,ttl=64/0,frag=no/0x2),icmp(type=8/0,code=0/0),
> > packets:0, bytes:0, used:0.0s,
> > actions:userspace(pid=0,slow_path(controller))
> > >
> > -in_port(2),eth(src=50:54:00:00:00:07/00:00:00:00:00:00,dst=50:54:00:00:00:05/00:00:00:00:00:00),eth_type(0x0800),ipv4(src=
> > 192.168.0.2/0.0.0.0,dst=192.168.0.1/0.0.0.0,proto=1/0,tos=0/0,ttl=64/0,frag=no/0x2),icmp(type=0/0,code=0/0),
> > packets:0, bytes:0, used:0.0s,
> > actions:userspace(pid=0,slow_path(controller))
> > >
> > +skb_priority(0),in_port(1),eth(src=50:54:00:00:00:05/00:00:00:00:00:00,dst=50:54:00:00:00:07/00:00:00:00:00:00),eth_type(0x0800),ipv4(src=
> > 192.168.0.1/0.0.0.0,dst=192.168.0.2/0.0.0.0,proto=1/0,tos=0/0,ttl=64/0,frag=no/0x2),icmp(type=8/0,code=0/0),
> > packets:0, bytes:0, used:0.0s,
> > actions:userspace(pid=0,slow_path(controller))
> > >
> > +skb_priority(0),in_port(2),eth(src=50:54:00:00:00:07/00:00:00:00:00:00,dst=50:54:00:00:00:05/00:00:00:00:00:00),eth_type(0x0800),ipv4(src=
> > 192.168.0.2/0.0.0.0,dst=192.168.0.1/0.0.0.0,proto=1/0,tos=0/0,ttl=64/0,frag=no/0x2),icmp(type=0/0,code=0/0),
> > packets:0, bytes:0, used:0.0s,
> > actions:userspace(pid=0,slow_path(controller))
> > >  ])
> > >
> > >  AT_CHECK([ovs-appctl dpif/dump-flows br1 | sort | STRIP_USED], [0], [dnl
> > >
> > -in_port(3),eth(src=50:54:00:00:00:09/00:00:00:00:00:00,dst=50:54:00:00:00:0a/00:00:00:00:00:00),eth_type(0x0800),ipv4(src=
> > 10.0.0.2/0.0.0.0,dst=10.0.0.1/0.0.0.0,proto=1/0,tos=0/0,ttl=64/0,frag=no/0x2),icmp(type=8/0,code=0/0),
> > packets:0, bytes:0, used:0.0s,
> > actions:userspace(pid=0,slow_path(controller))
> > >
> > +skb_priority(0),in_port(3),eth(src=50:54:00:00:00:09/00:00:00:00:00:00,dst=50:54:00:00:00:0a/00:00:00:00:00:00),eth_type(0x0800),ipv4(src=
> > 10.0.0.2/0.0.0.0,dst=10.0.0.1/0.0.0.0,proto=1/0,tos=0/0,ttl=64/0,frag=no/0x2),icmp(type=8/0,code=0/0),
> > packets:0, bytes:0, used:0.0s,
> > actions:userspace(pid=0,slow_path(controller))
> > >  ])
> > >
> > >  AT_CHECK([ovs-appctl dpif/del-flows br0])
> > > @@ -2123,7 +2123,7 @@ AT_CHECK([ovs-appctl dpif/dump-flows br0 | sort |
> > STRIP_USED], [0], [dnl
> > >  ])
> > >
> > >  AT_CHECK([ovs-appctl dpif/dump-flows br1 | sort | STRIP_USED], [0], [dnl
> > >
> > -in_port(3),eth(src=50:54:00:00:00:09/00:00:00:00:00:00,dst=50:54:00:00:00:0a/00:00:00:00:00:00),eth_type(0x0800),ipv4(src=
> > 10.0.0.2/0.0.0.0,dst=10.0.0.1/0.0.0.0,proto=1/0,tos=0/0,ttl=64/0,frag=no/0x2),icmp(type=8/0,code=0/0),
> > packets:0, bytes:0, used:0.0s,
> > actions:userspace(pid=0,slow_path(controller))
> > >
> > +skb_priority(0),in_port(3),eth(src=50:54:00:00:00:09/00:00:00:00:00:00,dst=50:54:00:00:00:0a/00:00:00:00:00:00),eth_type(0x0800),ipv4(src=
> > 10.0.0.2/0.0.0.0,dst=10.0.0.1/0.0.0.0,proto=1/0,tos=0/0,ttl=64/0,frag=no/0x2),icmp(type=8/0,code=0/0),
> > packets:0, bytes:0, used:0.0s,
> > actions:userspace(pid=0,slow_path(controller))
> > >  ])
> > >
> > >  OVS_VSWITCHD_STOP
> > > @@ -2170,10 +2170,10 @@ dummy@ovs-dummy: hit:13 missed:2
> > >  ])
> > >
> > >  AT_CHECK([ovs-appctl dpif/dump-flows br0 | STRIP_USED], [0], [dnl
> > >
> > -in_port(100),eth(src=50:54:00:00:00:05/00:00:00:00:00:00,dst=50:54:00:00:00:07/00:00:00:00:00:00),eth_type(0x0800),ipv4(src=
> > 192.168.0.1/0.0.0.0,dst=192.168.0.2/0.0.0.0,proto=1/0,tos=0/0,ttl=64/0,frag=no/0x2),icmp(type=8/0,code=0/0),
> > packets:9, bytes:540, used:0.0s, actions:101,3,2
> > >
> > +skb_priority(0),in_port(100),eth(src=50:54:00:00:00:05/00:00:00:00:00:00,dst=50:54:00:00:00:07/00:00:00:00:00:00),eth_type(0x0800),ipv4(src=
> > 192.168.0.1/0.0.0.0,dst=192.168.0.2/0.0.0.0,proto=1/0,tos=0/0,ttl=64/0,frag=no/0x2),icmp(type=8/0,code=0/0),
> > packets:9, bytes:540, used:0.0s, actions:101,3,2
> > >  ]),
> > >  AT_CHECK([ovs-appctl dpif/dump-flows br1 | STRIP_USED], [0], [dnl
> > >
> > -in_port(101),eth(src=50:54:00:00:00:07/00:00:00:00:00:00,dst=50:54:00:00:00:05/00:00:00:00:00:00),eth_type(0x0800),ipv4(src=
> > 192.168.0.2/0.0.0.0,dst=192.168.0.1/0.0.0.0,proto=1/0,tos=0/0,ttl=64/0,frag=no/0x2),icmp(type=8/0,code=0/0),
> > packets:4, bytes:240, used:0.0s, actions:100,2,3
> > >
> > +skb_priority(0),in_port(101),eth(src=50:54:00:00:00:07/00:00:00:00:00:00,dst=50:54:00:00:00:05/00:00:00:00:00:00),eth_type(0x0800),ipv4(src=
> > 192.168.0.2/0.0.0.0,dst=192.168.0.1/0.0.0.0,proto=1/0,tos=0/0,ttl=64/0,frag=no/0x2),icmp(type=8/0,code=0/0),
> > packets:4, bytes:240, used:0.0s, actions:100,2,3
> > >  ])
> > >
> > >  AT_CHECK([ovs-ofctl dump-ports br0 pbr0], [0], [dnl
> > > --
> > > 1.7.9.5
> > >
> > > _______________________________________________
> > > dev mailing list
> > > dev@openvswitch.org
> > > http://openvswitch.org/mailman/listinfo/dev
> > >
> >
_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to