[ovs-dev] [PATCH V9 13/31] netdev-tc-offloads: Implement netdev flow dump api using tc interface
Roi Dayan
roid at mellanox.com
Mon May 29 07:30:37 UTC 2017
On 28/05/2017 14:59, Roi Dayan wrote:
> From: Paul Blakey <paulb at mellanox.com>
>
> Signed-off-by: Paul Blakey <paulb at mellanox.com>
> Reviewed-by: Roi Dayan <roid at mellanox.com>
> Reviewed-by: Simon Horman <simon.horman at netronome.com>
> ---
> lib/netdev-tc-offloads.c | 184 ++++++++++++++++++++++++++++++++++++++++++++---
> 1 file changed, 175 insertions(+), 9 deletions(-)
>
> diff --git a/lib/netdev-tc-offloads.c b/lib/netdev-tc-offloads.c
> index 2c91b34..ba479a8 100644
> --- a/lib/netdev-tc-offloads.c
> +++ b/lib/netdev-tc-offloads.c
> @@ -150,7 +150,7 @@ get_ufid_tc_mapping(const ovs_u128 *ufid, int *prio, struct netdev **netdev)
> *
> * Returns true on success.
> */
> -static bool OVS_UNUSED
> +static bool
> find_ufid(int prio, int handle, struct netdev *netdev, ovs_u128 *ufid)
> {
> int ifindex = netdev_get_ifindex(netdev);
> @@ -188,9 +188,20 @@ int
> netdev_tc_flow_dump_create(struct netdev *netdev,
> struct netdev_flow_dump **dump_out)
> {
> - struct netdev_flow_dump *dump = xzalloc(sizeof *dump);
> + struct netdev_flow_dump *dump;
> + int ifindex;
> +
> + ifindex = netdev_get_ifindex(netdev);
> + if (ifindex < 0) {
> + VLOG_ERR_RL(&error_rl, "failed to get ifindex for %s: %s",
> + netdev_get_name(netdev), ovs_strerror(-ifindex));
> + return -ifindex;
> + }
>
> + dump = xzalloc(sizeof *dump);
> + dump->nl_dump = xzalloc(sizeof *dump->nl_dump);
> dump->netdev = netdev_ref(netdev);
> + tc_dump_flower_start(ifindex, dump->nl_dump);
>
> *dump_out = dump;
>
> @@ -200,21 +211,176 @@ netdev_tc_flow_dump_create(struct netdev *netdev,
> int
> netdev_tc_flow_dump_destroy(struct netdev_flow_dump *dump)
> {
> + nl_dump_done(dump->nl_dump);
> netdev_close(dump->netdev);
> + free(dump->nl_dump);
> free(dump);
> + return 0;
> +}
> +
> +static int
> +parse_tc_flower_to_match(struct tc_flower *flower,
> + struct match *match,
> + struct nlattr **actions,
> + struct dpif_flow_stats *stats,
> + struct ofpbuf *buf) {
> + size_t act_off;
> + struct tc_flower_key *key = &flower->key;
> + struct tc_flower_key *mask = &flower->mask;
> + odp_port_t outport = 0;
> +
> + if (flower->ifindex_out) {
> + outport = netdev_ifindex_to_odp_port(flower->ifindex_out);
> + if (!outport) {
> + return ENOENT;
> + }
> + }
> +
> + ofpbuf_clear(buf);
> +
> + match_init_catchall(match);
> + match_set_dl_type(match, key->eth_type);
> + match_set_dl_src_masked(match, key->src_mac, mask->src_mac);
> + match_set_dl_dst_masked(match, key->dst_mac, mask->dst_mac);
> + if (key->vlan_id || key->vlan_prio) {
> + match_set_dl_vlan(match, htons(key->vlan_id));
> + match_set_dl_vlan_pcp(match, key->vlan_prio);
> + match_set_dl_type(match, key->encap_eth_type);
> + }
> +
> + if (key->ip_proto &&
> + (key->eth_type == htons(ETH_P_IP)
> + || key->eth_type == htons(ETH_P_IPV6))) {
> + match_set_nw_proto(match, key->ip_proto);
> + }
> +
> + match_set_nw_src_masked(match, key->ipv4.ipv4_src, mask->ipv4.ipv4_src);
> + match_set_nw_dst_masked(match, key->ipv4.ipv4_dst, mask->ipv4.ipv4_dst);
> +
> + match_set_ipv6_src_masked(match,
> + &key->ipv6.ipv6_src, &mask->ipv6.ipv6_src);
> + match_set_ipv6_dst_masked(match,
> + &key->ipv6.ipv6_dst, &mask->ipv6.ipv6_dst);
> +
> + match_set_tp_dst_masked(match, key->dst_port, mask->dst_port);
> + match_set_tp_src_masked(match, key->src_port, mask->src_port);
> +
> + if (flower->tunnel.tunnel) {
> + match_set_tun_id(match, flower->tunnel.id);
> + if (flower->tunnel.ipv4.ipv4_dst) {
> + match_set_tun_src(match, flower->tunnel.ipv4.ipv4_src);
> + match_set_tun_dst(match, flower->tunnel.ipv4.ipv4_dst);
> + } else if (!is_all_zeros(&flower->tunnel.ipv6.ipv6_dst,
> + sizeof flower->tunnel.ipv6.ipv6_dst)) {
> + match_set_tun_ipv6_src(match, &flower->tunnel.ipv6.ipv6_src);
> + match_set_tun_ipv6_dst(match, &flower->tunnel.ipv6.ipv6_dst);
> + }
> + match_set_tp_dst(match, flower->tunnel.tp_dst);
We have a bug here. we accidently set tp_dst instead of tunnel.tp_dst.
Should be something like:
if (flower->tunnel.tp_dst) {
match_set_tun_dst(match, flower->tunnel.tp_dst);
}
fixed for V10. will wait for more comments before sending V10 though.
> + }
> +
> + act_off = nl_msg_start_nested(buf, OVS_FLOW_ATTR_ACTIONS);
> + {
> + if (flower->vlan_pop) {
> + nl_msg_put_flag(buf, OVS_ACTION_ATTR_POP_VLAN);
> + }
> +
> + if (flower->vlan_push_id || flower->vlan_push_prio) {
> + struct ovs_action_push_vlan *push;
> + push = nl_msg_put_unspec_zero(buf, OVS_ACTION_ATTR_PUSH_VLAN,
> + sizeof *push);
> +
> + push->vlan_tpid = htons(ETH_TYPE_VLAN);
> + push->vlan_tci = htons(flower->vlan_push_id
> + | (flower->vlan_push_prio << 13)
> + | VLAN_CFI);
> + }
> +
> + if (flower->set.set) {
> + size_t set_offset = nl_msg_start_nested(buf, OVS_ACTION_ATTR_SET);
> + size_t tunnel_offset =
> + nl_msg_start_nested(buf, OVS_KEY_ATTR_TUNNEL);
> +
> + nl_msg_put_be64(buf, OVS_TUNNEL_KEY_ATTR_ID, flower->set.id);
> + if (flower->set.ipv4.ipv4_src) {
> + nl_msg_put_be32(buf, OVS_TUNNEL_KEY_ATTR_IPV4_SRC,
> + flower->set.ipv4.ipv4_src);
> + }
> + if (flower->set.ipv4.ipv4_dst) {
> + nl_msg_put_be32(buf, OVS_TUNNEL_KEY_ATTR_IPV4_DST,
> + flower->set.ipv4.ipv4_dst);
> + }
> + if (!is_all_zeros(&flower->set.ipv6.ipv6_src,
> + sizeof flower->set.ipv6.ipv6_src)) {
> + nl_msg_put_in6_addr(buf, OVS_TUNNEL_KEY_ATTR_IPV6_SRC,
> + &flower->set.ipv6.ipv6_src);
> + }
> + if (!is_all_zeros(&flower->set.ipv6.ipv6_dst,
> + sizeof flower->set.ipv6.ipv6_dst)) {
> + nl_msg_put_in6_addr(buf, OVS_TUNNEL_KEY_ATTR_IPV6_DST,
> + &flower->set.ipv6.ipv6_dst);
> + }
> + nl_msg_put_be16(buf, OVS_TUNNEL_KEY_ATTR_TP_DST,
> + flower->set.tp_dst);
> +
> + nl_msg_end_nested(buf, tunnel_offset);
> + nl_msg_end_nested(buf, set_offset);
> + }
> +
> + if (flower->ifindex_out > 0) {
> + nl_msg_put_u32(buf, OVS_ACTION_ATTR_OUTPUT, odp_to_u32(outport));
> + }
> +
> + }
> + nl_msg_end_nested(buf, act_off);
> +
> + *actions = ofpbuf_at_assert(buf, act_off, sizeof(struct nlattr));
> +
> + if (stats) {
> + memset(stats, 0, sizeof *stats);
> + stats->n_packets = get_32aligned_u64(&flower->stats.n_packets);
> + stats->n_bytes = get_32aligned_u64(&flower->stats.n_bytes);
> + stats->used = flower->lastused;
> + }
>
> return 0;
> }
>
> bool
> -netdev_tc_flow_dump_next(struct netdev_flow_dump *dump OVS_UNUSED,
> - struct match *match OVS_UNUSED,
> - struct nlattr **actions OVS_UNUSED,
> - struct dpif_flow_stats *stats OVS_UNUSED,
> - ovs_u128 *ufid OVS_UNUSED,
> - struct ofpbuf *rbuffer OVS_UNUSED,
> - struct ofpbuf *wbuffer OVS_UNUSED)
> +netdev_tc_flow_dump_next(struct netdev_flow_dump *dump,
> + struct match *match,
> + struct nlattr **actions,
> + struct dpif_flow_stats *stats,
> + ovs_u128 *ufid,
> + struct ofpbuf *rbuffer,
> + struct ofpbuf *wbuffer)
> {
> + struct ofpbuf nl_flow;
> +
> + while (nl_dump_next(dump->nl_dump, &nl_flow, rbuffer)) {
> + struct tc_flower flower;
> + struct netdev *netdev = dump->netdev;
> +
> + if (parse_netlink_to_tc_flower(&nl_flow, &flower)) {
> + continue;
> + }
> +
> + if (parse_tc_flower_to_match(&flower, match, actions, stats,
> + wbuffer)) {
> + continue;
> + }
> +
> + if (flower.act_cookie.len) {
> + *ufid = *((ovs_u128 *) flower.act_cookie.data);
> + } else if (!find_ufid(flower.prio, flower.handle, netdev, ufid)) {
> + continue;
> + }
> +
> + match->wc.masks.in_port.odp_port = u32_to_odp(UINT32_MAX);
> + match->flow.in_port.odp_port = dump->port;
> +
> + return true;
> + }
> +
> return false;
> }
>
>
More information about the dev
mailing list