Message ID | 1496922410-36853-16-git-send-email-roid@mellanox.com |
---|---|
State | Superseded |
Headers | show |
On Thu, Jun 08, 2017 at 02:46:32PM +0300, Roi Dayan wrote: > From: Paul Blakey <paulb@mellanox.com> > > Signed-off-by: Paul Blakey <paulb@mellanox.com> > Reviewed-by: Roi Dayan <roid@mellanox.com> > Reviewed-by: Simon Horman <simon.horman@netronome.com> > --- Acked-by: Flavio Leitner <fbl@sysclose.org>
On 08/06/2017 14:46, Roi Dayan wrote: > From: Paul Blakey <paulb@mellanox.com> > > Signed-off-by: Paul Blakey <paulb@mellanox.com> > Reviewed-by: Roi Dayan <roid@mellanox.com> > Reviewed-by: Simon Horman <simon.horman@netronome.com> > --- > lib/netdev-tc-offloads.c | 186 ++++++++++++++++++++++++++++++++++++++++++++--- > 1 file changed, 177 insertions(+), 9 deletions(-) > > diff --git a/lib/netdev-tc-offloads.c b/lib/netdev-tc-offloads.c > index 0786048..4b14c5c 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,178 @@ 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) { we should probably check if key->eth_type is vlan eth type. > + 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))) { we missed here. key is flower key and for vlan this will be vlan eth type so we need to compare to match->dl_type which is little up being set to the encap eth type if in vlan. > + 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); > + } > + if (flower->tunnel.tp_dst) { > + match_set_tun_tp_dst(match, flower->tunnel.tp_dst); > + } > + } > + > + 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; > } > >
diff --git a/lib/netdev-tc-offloads.c b/lib/netdev-tc-offloads.c index 0786048..4b14c5c 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,178 @@ 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); + } + if (flower->tunnel.tp_dst) { + match_set_tun_tp_dst(match, flower->tunnel.tp_dst); + } + } + + 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; }