|
@@ -5234,7 +5234,6 @@ static void mlxsw_sp_router_fib4_event_work(struct work_struct *work)
|
|
|
struct mlxsw_sp_fib_event_work *fib_work =
|
|
|
container_of(work, struct mlxsw_sp_fib_event_work, work);
|
|
|
struct mlxsw_sp *mlxsw_sp = fib_work->mlxsw_sp;
|
|
|
- struct fib_rule *rule;
|
|
|
bool replace, append;
|
|
|
int err;
|
|
|
|
|
@@ -5256,12 +5255,11 @@ static void mlxsw_sp_router_fib4_event_work(struct work_struct *work)
|
|
|
mlxsw_sp_router_fib4_del(mlxsw_sp, &fib_work->fen_info);
|
|
|
fib_info_put(fib_work->fen_info.fi);
|
|
|
break;
|
|
|
- case FIB_EVENT_RULE_ADD: /* fall through */
|
|
|
- case FIB_EVENT_RULE_DEL:
|
|
|
- rule = fib_work->fr_info.rule;
|
|
|
- if (!fib4_rule_default(rule) && !rule->l3mdev)
|
|
|
- mlxsw_sp_router_fib_abort(mlxsw_sp);
|
|
|
- fib_rule_put(rule);
|
|
|
+ case FIB_EVENT_RULE_ADD:
|
|
|
+ /* if we get here, a rule was added that we do not support.
|
|
|
+ * just do the fib_abort
|
|
|
+ */
|
|
|
+ mlxsw_sp_router_fib_abort(mlxsw_sp);
|
|
|
break;
|
|
|
case FIB_EVENT_NH_ADD: /* fall through */
|
|
|
case FIB_EVENT_NH_DEL:
|
|
@@ -5279,7 +5277,6 @@ static void mlxsw_sp_router_fib6_event_work(struct work_struct *work)
|
|
|
struct mlxsw_sp_fib_event_work *fib_work =
|
|
|
container_of(work, struct mlxsw_sp_fib_event_work, work);
|
|
|
struct mlxsw_sp *mlxsw_sp = fib_work->mlxsw_sp;
|
|
|
- struct fib_rule *rule;
|
|
|
bool replace;
|
|
|
int err;
|
|
|
|
|
@@ -5298,12 +5295,11 @@ static void mlxsw_sp_router_fib6_event_work(struct work_struct *work)
|
|
|
mlxsw_sp_router_fib6_del(mlxsw_sp, fib_work->fen6_info.rt);
|
|
|
mlxsw_sp_rt6_release(fib_work->fen6_info.rt);
|
|
|
break;
|
|
|
- case FIB_EVENT_RULE_ADD: /* fall through */
|
|
|
- case FIB_EVENT_RULE_DEL:
|
|
|
- rule = fib_work->fr_info.rule;
|
|
|
- if (!fib6_rule_default(rule) && !rule->l3mdev)
|
|
|
- mlxsw_sp_router_fib_abort(mlxsw_sp);
|
|
|
- fib_rule_put(rule);
|
|
|
+ case FIB_EVENT_RULE_ADD:
|
|
|
+ /* if we get here, a rule was added that we do not support.
|
|
|
+ * just do the fib_abort
|
|
|
+ */
|
|
|
+ mlxsw_sp_router_fib_abort(mlxsw_sp);
|
|
|
break;
|
|
|
}
|
|
|
rtnl_unlock();
|
|
@@ -5315,7 +5311,6 @@ static void mlxsw_sp_router_fibmr_event_work(struct work_struct *work)
|
|
|
struct mlxsw_sp_fib_event_work *fib_work =
|
|
|
container_of(work, struct mlxsw_sp_fib_event_work, work);
|
|
|
struct mlxsw_sp *mlxsw_sp = fib_work->mlxsw_sp;
|
|
|
- struct fib_rule *rule;
|
|
|
bool replace;
|
|
|
int err;
|
|
|
|
|
@@ -5347,12 +5342,11 @@ static void mlxsw_sp_router_fibmr_event_work(struct work_struct *work)
|
|
|
&fib_work->ven_info);
|
|
|
dev_put(fib_work->ven_info.dev);
|
|
|
break;
|
|
|
- case FIB_EVENT_RULE_ADD: /* fall through */
|
|
|
- case FIB_EVENT_RULE_DEL:
|
|
|
- rule = fib_work->fr_info.rule;
|
|
|
- if (!ipmr_rule_default(rule) && !rule->l3mdev)
|
|
|
- mlxsw_sp_router_fib_abort(mlxsw_sp);
|
|
|
- fib_rule_put(rule);
|
|
|
+ case FIB_EVENT_RULE_ADD:
|
|
|
+ /* if we get here, a rule was added that we do not support.
|
|
|
+ * just do the fib_abort
|
|
|
+ */
|
|
|
+ mlxsw_sp_router_fib_abort(mlxsw_sp);
|
|
|
break;
|
|
|
}
|
|
|
rtnl_unlock();
|
|
@@ -5363,7 +5357,6 @@ static void mlxsw_sp_router_fib4_event(struct mlxsw_sp_fib_event_work *fib_work,
|
|
|
struct fib_notifier_info *info)
|
|
|
{
|
|
|
struct fib_entry_notifier_info *fen_info;
|
|
|
- struct fib_rule_notifier_info *fr_info;
|
|
|
struct fib_nh_notifier_info *fnh_info;
|
|
|
|
|
|
switch (fib_work->event) {
|
|
@@ -5379,13 +5372,6 @@ static void mlxsw_sp_router_fib4_event(struct mlxsw_sp_fib_event_work *fib_work,
|
|
|
*/
|
|
|
fib_info_hold(fib_work->fen_info.fi);
|
|
|
break;
|
|
|
- case FIB_EVENT_RULE_ADD: /* fall through */
|
|
|
- case FIB_EVENT_RULE_DEL:
|
|
|
- fr_info = container_of(info, struct fib_rule_notifier_info,
|
|
|
- info);
|
|
|
- fib_work->fr_info = *fr_info;
|
|
|
- fib_rule_get(fib_work->fr_info.rule);
|
|
|
- break;
|
|
|
case FIB_EVENT_NH_ADD: /* fall through */
|
|
|
case FIB_EVENT_NH_DEL:
|
|
|
fnh_info = container_of(info, struct fib_nh_notifier_info,
|
|
@@ -5400,7 +5386,6 @@ static void mlxsw_sp_router_fib6_event(struct mlxsw_sp_fib_event_work *fib_work,
|
|
|
struct fib_notifier_info *info)
|
|
|
{
|
|
|
struct fib6_entry_notifier_info *fen6_info;
|
|
|
- struct fib_rule_notifier_info *fr_info;
|
|
|
|
|
|
switch (fib_work->event) {
|
|
|
case FIB_EVENT_ENTRY_REPLACE: /* fall through */
|
|
@@ -5411,13 +5396,6 @@ static void mlxsw_sp_router_fib6_event(struct mlxsw_sp_fib_event_work *fib_work,
|
|
|
fib_work->fen6_info = *fen6_info;
|
|
|
rt6_hold(fib_work->fen6_info.rt);
|
|
|
break;
|
|
|
- case FIB_EVENT_RULE_ADD: /* fall through */
|
|
|
- case FIB_EVENT_RULE_DEL:
|
|
|
- fr_info = container_of(info, struct fib_rule_notifier_info,
|
|
|
- info);
|
|
|
- fib_work->fr_info = *fr_info;
|
|
|
- fib_rule_get(fib_work->fr_info.rule);
|
|
|
- break;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -5437,12 +5415,47 @@ mlxsw_sp_router_fibmr_event(struct mlxsw_sp_fib_event_work *fib_work,
|
|
|
memcpy(&fib_work->ven_info, info, sizeof(fib_work->ven_info));
|
|
|
dev_hold(fib_work->ven_info.dev);
|
|
|
break;
|
|
|
- case FIB_EVENT_RULE_ADD: /* fall through */
|
|
|
- case FIB_EVENT_RULE_DEL:
|
|
|
- memcpy(&fib_work->fr_info, info, sizeof(fib_work->fr_info));
|
|
|
- fib_rule_get(fib_work->fr_info.rule);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static int mlxsw_sp_router_fib_rule_event(unsigned long event,
|
|
|
+ struct fib_notifier_info *info,
|
|
|
+ struct mlxsw_sp *mlxsw_sp)
|
|
|
+{
|
|
|
+ struct netlink_ext_ack *extack = info->extack;
|
|
|
+ struct fib_rule_notifier_info *fr_info;
|
|
|
+ struct fib_rule *rule;
|
|
|
+ int err = 0;
|
|
|
+
|
|
|
+ /* nothing to do at the moment */
|
|
|
+ if (event == FIB_EVENT_RULE_DEL)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ if (mlxsw_sp->router->aborted)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ fr_info = container_of(info, struct fib_rule_notifier_info, info);
|
|
|
+ rule = fr_info->rule;
|
|
|
+
|
|
|
+ switch (info->family) {
|
|
|
+ case AF_INET:
|
|
|
+ if (!fib4_rule_default(rule) && !rule->l3mdev)
|
|
|
+ err = -1;
|
|
|
+ break;
|
|
|
+ case AF_INET6:
|
|
|
+ if (!fib6_rule_default(rule) && !rule->l3mdev)
|
|
|
+ err = -1;
|
|
|
+ break;
|
|
|
+ case RTNL_FAMILY_IPMR:
|
|
|
+ if (!ipmr_rule_default(rule) && !rule->l3mdev)
|
|
|
+ err = -1;
|
|
|
break;
|
|
|
}
|
|
|
+
|
|
|
+ if (err < 0)
|
|
|
+ NL_SET_ERR_MSG(extack, "spectrum: FIB rules not supported. Aborting offload");
|
|
|
+
|
|
|
+ return err;
|
|
|
}
|
|
|
|
|
|
/* Called with rcu_read_lock() */
|
|
@@ -5452,17 +5465,28 @@ static int mlxsw_sp_router_fib_event(struct notifier_block *nb,
|
|
|
struct mlxsw_sp_fib_event_work *fib_work;
|
|
|
struct fib_notifier_info *info = ptr;
|
|
|
struct mlxsw_sp_router *router;
|
|
|
+ int err;
|
|
|
|
|
|
if (!net_eq(info->net, &init_net) ||
|
|
|
(info->family != AF_INET && info->family != AF_INET6 &&
|
|
|
info->family != RTNL_FAMILY_IPMR))
|
|
|
return NOTIFY_DONE;
|
|
|
|
|
|
+ router = container_of(nb, struct mlxsw_sp_router, fib_nb);
|
|
|
+
|
|
|
+ switch (event) {
|
|
|
+ case FIB_EVENT_RULE_ADD: /* fall through */
|
|
|
+ case FIB_EVENT_RULE_DEL:
|
|
|
+ err = mlxsw_sp_router_fib_rule_event(event, info,
|
|
|
+ router->mlxsw_sp);
|
|
|
+ if (!err)
|
|
|
+ return NOTIFY_DONE;
|
|
|
+ }
|
|
|
+
|
|
|
fib_work = kzalloc(sizeof(*fib_work), GFP_ATOMIC);
|
|
|
if (WARN_ON(!fib_work))
|
|
|
return NOTIFY_BAD;
|
|
|
|
|
|
- router = container_of(nb, struct mlxsw_sp_router, fib_nb);
|
|
|
fib_work->mlxsw_sp = router->mlxsw_sp;
|
|
|
fib_work->event = event;
|
|
|
|