|
|
@@ -1206,7 +1206,6 @@ mlxsw_sp_ipip_entry_get(struct mlxsw_sp *mlxsw_sp,
|
|
|
{
|
|
|
u32 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(ol_dev);
|
|
|
struct mlxsw_sp_router *router = mlxsw_sp->router;
|
|
|
- struct mlxsw_sp_fib_entry *decap_fib_entry;
|
|
|
struct mlxsw_sp_ipip_entry *ipip_entry;
|
|
|
enum mlxsw_sp_l3proto ul_proto;
|
|
|
union mlxsw_sp_l3addr saddr;
|
|
|
@@ -1231,11 +1230,6 @@ mlxsw_sp_ipip_entry_get(struct mlxsw_sp *mlxsw_sp,
|
|
|
if (IS_ERR(ipip_entry))
|
|
|
return ipip_entry;
|
|
|
|
|
|
- decap_fib_entry = mlxsw_sp_ipip_entry_find_decap(mlxsw_sp, ipip_entry);
|
|
|
- if (decap_fib_entry)
|
|
|
- mlxsw_sp_ipip_entry_promote_decap(mlxsw_sp, ipip_entry,
|
|
|
- decap_fib_entry);
|
|
|
-
|
|
|
list_add_tail(&ipip_entry->ipip_list_node,
|
|
|
&mlxsw_sp->router->ipip_list);
|
|
|
|
|
|
@@ -1250,8 +1244,6 @@ mlxsw_sp_ipip_entry_put(struct mlxsw_sp *mlxsw_sp,
|
|
|
{
|
|
|
if (--ipip_entry->ref_count == 0) {
|
|
|
list_del(&ipip_entry->ipip_list_node);
|
|
|
- if (ipip_entry->decap_fib_entry)
|
|
|
- mlxsw_sp_ipip_entry_demote_decap(mlxsw_sp, ipip_entry);
|
|
|
mlxsw_sp_ipip_entry_destroy(ipip_entry);
|
|
|
}
|
|
|
}
|
|
|
@@ -1314,6 +1306,103 @@ static bool mlxsw_sp_netdev_ipip_type(const struct mlxsw_sp *mlxsw_sp,
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
+bool mlxsw_sp_netdev_is_ipip(const struct mlxsw_sp *mlxsw_sp,
|
|
|
+ const struct net_device *dev)
|
|
|
+{
|
|
|
+ return mlxsw_sp_netdev_ipip_type(mlxsw_sp, dev, NULL);
|
|
|
+}
|
|
|
+
|
|
|
+static struct mlxsw_sp_ipip_entry *
|
|
|
+mlxsw_sp_ipip_entry_find_by_ol_dev(struct mlxsw_sp *mlxsw_sp,
|
|
|
+ const struct net_device *ol_dev)
|
|
|
+{
|
|
|
+ struct mlxsw_sp_ipip_entry *ipip_entry;
|
|
|
+
|
|
|
+ list_for_each_entry(ipip_entry, &mlxsw_sp->router->ipip_list,
|
|
|
+ ipip_list_node)
|
|
|
+ if (ipip_entry->ol_dev == ol_dev)
|
|
|
+ return ipip_entry;
|
|
|
+
|
|
|
+ return NULL;
|
|
|
+}
|
|
|
+
|
|
|
+static int mlxsw_sp_netdevice_ipip_reg_event(struct mlxsw_sp *mlxsw_sp,
|
|
|
+ struct net_device *ol_dev)
|
|
|
+{
|
|
|
+ struct mlxsw_sp_router *router = mlxsw_sp->router;
|
|
|
+ struct mlxsw_sp_ipip_entry *ipip_entry;
|
|
|
+ enum mlxsw_sp_ipip_type ipipt;
|
|
|
+
|
|
|
+ mlxsw_sp_netdev_ipip_type(mlxsw_sp, ol_dev, &ipipt);
|
|
|
+ if (router->ipip_ops_arr[ipipt]->can_offload(mlxsw_sp, ol_dev,
|
|
|
+ MLXSW_SP_L3_PROTO_IPV4) ||
|
|
|
+ router->ipip_ops_arr[ipipt]->can_offload(mlxsw_sp, ol_dev,
|
|
|
+ MLXSW_SP_L3_PROTO_IPV6)) {
|
|
|
+ ipip_entry = mlxsw_sp_ipip_entry_get(mlxsw_sp, ipipt, ol_dev);
|
|
|
+ if (IS_ERR(ipip_entry))
|
|
|
+ return PTR_ERR(ipip_entry);
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static void mlxsw_sp_netdevice_ipip_unreg_event(struct mlxsw_sp *mlxsw_sp,
|
|
|
+ struct net_device *ol_dev)
|
|
|
+{
|
|
|
+ struct mlxsw_sp_ipip_entry *ipip_entry;
|
|
|
+
|
|
|
+ ipip_entry = mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp, ol_dev);
|
|
|
+ if (ipip_entry)
|
|
|
+ mlxsw_sp_ipip_entry_put(mlxsw_sp, ipip_entry);
|
|
|
+}
|
|
|
+
|
|
|
+static int mlxsw_sp_netdevice_ipip_up_event(struct mlxsw_sp *mlxsw_sp,
|
|
|
+ struct net_device *ol_dev)
|
|
|
+{
|
|
|
+ struct mlxsw_sp_fib_entry *decap_fib_entry;
|
|
|
+ struct mlxsw_sp_ipip_entry *ipip_entry;
|
|
|
+
|
|
|
+ ipip_entry = mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp, ol_dev);
|
|
|
+ if (ipip_entry) {
|
|
|
+ decap_fib_entry = mlxsw_sp_ipip_entry_find_decap(mlxsw_sp,
|
|
|
+ ipip_entry);
|
|
|
+ if (decap_fib_entry)
|
|
|
+ mlxsw_sp_ipip_entry_promote_decap(mlxsw_sp, ipip_entry,
|
|
|
+ decap_fib_entry);
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static void mlxsw_sp_netdevice_ipip_down_event(struct mlxsw_sp *mlxsw_sp,
|
|
|
+ struct net_device *ol_dev)
|
|
|
+{
|
|
|
+ struct mlxsw_sp_ipip_entry *ipip_entry;
|
|
|
+
|
|
|
+ ipip_entry = mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp, ol_dev);
|
|
|
+ if (ipip_entry && ipip_entry->decap_fib_entry)
|
|
|
+ mlxsw_sp_ipip_entry_demote_decap(mlxsw_sp, ipip_entry);
|
|
|
+}
|
|
|
+
|
|
|
+int mlxsw_sp_netdevice_ipip_event(struct mlxsw_sp *mlxsw_sp,
|
|
|
+ struct net_device *ol_dev,
|
|
|
+ unsigned long event)
|
|
|
+{
|
|
|
+ switch (event) {
|
|
|
+ case NETDEV_REGISTER:
|
|
|
+ return mlxsw_sp_netdevice_ipip_reg_event(mlxsw_sp, ol_dev);
|
|
|
+ case NETDEV_UNREGISTER:
|
|
|
+ mlxsw_sp_netdevice_ipip_unreg_event(mlxsw_sp, ol_dev);
|
|
|
+ return 0;
|
|
|
+ case NETDEV_UP:
|
|
|
+ return mlxsw_sp_netdevice_ipip_up_event(mlxsw_sp, ol_dev);
|
|
|
+ case NETDEV_DOWN:
|
|
|
+ mlxsw_sp_netdevice_ipip_down_event(mlxsw_sp, ol_dev);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
struct mlxsw_sp_neigh_key {
|
|
|
struct neighbour *n;
|
|
|
};
|