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;
 
                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:
        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;
 
                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();
        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;
 
                                              &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();
                                       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) {
                 */
                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,
                                       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 */
                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;
        }
 }
 
                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() */
        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;