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 <[email protected]>
> ---
> 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 <[email protected]>
> /* 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
> [email protected]
> http://openvswitch.org/mailman/listinfo/dev
>
_______________________________________________
dev mailing list
[email protected]
http://openvswitch.org/mailman/listinfo/dev