|
@@ -44,6 +44,7 @@
|
|
|
#include <net/tc_act/tc_tunnel_key.h>
|
|
|
#include <net/tc_act/tc_pedit.h>
|
|
|
#include <net/vxlan.h>
|
|
|
+#include <net/arp.h>
|
|
|
#include "en.h"
|
|
|
#include "en_rep.h"
|
|
|
#include "en_tc.h"
|
|
@@ -278,6 +279,7 @@ void mlx5e_tc_encap_flows_add(struct mlx5e_priv *priv,
|
|
|
return;
|
|
|
}
|
|
|
e->flags |= MLX5_ENCAP_ENTRY_VALID;
|
|
|
+ mlx5e_rep_queue_neigh_stats_work(priv);
|
|
|
|
|
|
list_for_each_entry(flow, &e->flows, encap) {
|
|
|
flow->esw_attr->encap_id = e->encap_id;
|
|
@@ -315,6 +317,58 @@ void mlx5e_tc_encap_flows_del(struct mlx5e_priv *priv,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+void mlx5e_tc_update_neigh_used_value(struct mlx5e_neigh_hash_entry *nhe)
|
|
|
+{
|
|
|
+ struct mlx5e_neigh *m_neigh = &nhe->m_neigh;
|
|
|
+ u64 bytes, packets, lastuse = 0;
|
|
|
+ struct mlx5e_tc_flow *flow;
|
|
|
+ struct mlx5e_encap_entry *e;
|
|
|
+ struct mlx5_fc *counter;
|
|
|
+ struct neigh_table *tbl;
|
|
|
+ bool neigh_used = false;
|
|
|
+ struct neighbour *n;
|
|
|
+
|
|
|
+ if (m_neigh->family == AF_INET)
|
|
|
+ tbl = &arp_tbl;
|
|
|
+#if IS_ENABLED(CONFIG_IPV6)
|
|
|
+ else if (m_neigh->family == AF_INET6)
|
|
|
+ tbl = ipv6_stub->nd_tbl;
|
|
|
+#endif
|
|
|
+ else
|
|
|
+ return;
|
|
|
+
|
|
|
+ list_for_each_entry(e, &nhe->encap_list, encap_list) {
|
|
|
+ if (!(e->flags & MLX5_ENCAP_ENTRY_VALID))
|
|
|
+ continue;
|
|
|
+ list_for_each_entry(flow, &e->flows, encap) {
|
|
|
+ if (flow->flags & MLX5E_TC_FLOW_OFFLOADED) {
|
|
|
+ counter = mlx5_flow_rule_counter(flow->rule);
|
|
|
+ mlx5_fc_query_cached(counter, &bytes, &packets, &lastuse);
|
|
|
+ if (time_after((unsigned long)lastuse, nhe->reported_lastuse)) {
|
|
|
+ neigh_used = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (neigh_used) {
|
|
|
+ nhe->reported_lastuse = jiffies;
|
|
|
+
|
|
|
+ /* find the relevant neigh according to the cached device and
|
|
|
+ * dst ip pair
|
|
|
+ */
|
|
|
+ n = neigh_lookup(tbl, &m_neigh->dst_ip, m_neigh->dev);
|
|
|
+ if (!n) {
|
|
|
+ WARN(1, "The neighbour already freed\n");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ neigh_event_send(n, NULL);
|
|
|
+ neigh_release(n);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
static void mlx5e_detach_encap(struct mlx5e_priv *priv,
|
|
|
struct mlx5e_tc_flow *flow)
|
|
|
{
|
|
@@ -1315,6 +1369,7 @@ static int mlx5e_create_encap_header_ipv4(struct mlx5e_priv *priv,
|
|
|
* entry in the neigh hash table when a user deletes a rule
|
|
|
*/
|
|
|
e->m_neigh.dev = n->dev;
|
|
|
+ e->m_neigh.family = n->ops->family;
|
|
|
memcpy(&e->m_neigh.dst_ip, n->primary_key, n->tbl->key_len);
|
|
|
e->out_dev = out_dev;
|
|
|
|
|
@@ -1359,6 +1414,7 @@ static int mlx5e_create_encap_header_ipv4(struct mlx5e_priv *priv,
|
|
|
goto destroy_neigh_entry;
|
|
|
|
|
|
e->flags |= MLX5_ENCAP_ENTRY_VALID;
|
|
|
+ mlx5e_rep_queue_neigh_stats_work(netdev_priv(out_dev));
|
|
|
neigh_release(n);
|
|
|
return err;
|
|
|
|
|
@@ -1418,6 +1474,7 @@ static int mlx5e_create_encap_header_ipv6(struct mlx5e_priv *priv,
|
|
|
* entry in the neigh hash table when a user deletes a rule
|
|
|
*/
|
|
|
e->m_neigh.dev = n->dev;
|
|
|
+ e->m_neigh.family = n->ops->family;
|
|
|
memcpy(&e->m_neigh.dst_ip, n->primary_key, n->tbl->key_len);
|
|
|
e->out_dev = out_dev;
|
|
|
|
|
@@ -1463,6 +1520,7 @@ static int mlx5e_create_encap_header_ipv6(struct mlx5e_priv *priv,
|
|
|
goto destroy_neigh_entry;
|
|
|
|
|
|
e->flags |= MLX5_ENCAP_ENTRY_VALID;
|
|
|
+ mlx5e_rep_queue_neigh_stats_work(netdev_priv(out_dev));
|
|
|
neigh_release(n);
|
|
|
return err;
|
|
|
|