]> git.proxmox.com Git - mirror_frr.git/blobdiff - zebra/kernel_netlink.c
Merge pull request #13465 from donaldsharp/ospf_metric_ifindex
[mirror_frr.git] / zebra / kernel_netlink.c
index a8b56bb8f2aaec18b7d8cca85804b42d00294c9c..78b1dfe27633039f3c515d01883d42abb49f587b 100644 (file)
@@ -1,21 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
 /* Kernel communication using netlink interface.
  * Copyright (C) 1999 Kunihiro Ishiguro
- *
- * This file is part of GNU Zebra.
- *
- * GNU Zebra is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * GNU Zebra is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; see the file COPYING; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
 #include <zebra.h>
@@ -30,7 +15,7 @@
 #include "table.h"
 #include "memory.h"
 #include "rib.h"
-#include "thread.h"
+#include "frrevent.h"
 #include "privs.h"
 #include "nexthop.h"
 #include "vrf.h"
@@ -124,6 +109,9 @@ static const struct message nlmsg_str[] = {{RTM_NEWROUTE, "RTM_NEWROUTE"},
                                           {RTM_NEWTFILTER, "RTM_NEWTFILTER"},
                                           {RTM_DELTFILTER, "RTM_DELTFILTER"},
                                           {RTM_GETTFILTER, "RTM_GETTFILTER"},
+                                          {RTM_NEWVLAN, "RTM_NEWVLAN"},
+                                          {RTM_DELVLAN, "RTM_DELVLAN"},
+                                          {RTM_GETVLAN, "RTM_GETVLAN"},
                                           {0}};
 
 static const struct message rtproto_str[] = {
@@ -168,7 +156,7 @@ static const struct message rttype_str[] = {{RTN_UNSPEC, "none"},
                                            {RTN_XRESOLVE, "resolver"},
                                            {0}};
 
-extern struct thread_master *master;
+extern struct event_loop *master;
 
 extern struct zebra_privs_t zserv_privs;
 
@@ -202,13 +190,13 @@ struct nl_batch {
 
        const struct zebra_dplane_info *zns;
 
-       struct dplane_ctx_q ctx_list;
+       struct dplane_ctx_list_head ctx_list;
 
        /*
         * Pointer to the queue of completed contexts outbound back
         * towards the dataplane module.
         */
-       struct dplane_ctx_q *ctx_out_q;
+       struct dplane_ctx_list_head *ctx_out_q;
 };
 
 int netlink_config_write_helper(struct vty *vty)
@@ -423,6 +411,19 @@ static int netlink_information_fetch(struct nlmsghdr *h, ns_id_t ns_id,
                return netlink_nexthop_change(h, ns_id, startup);
        case RTM_DELNEXTHOP:
                return netlink_nexthop_change(h, ns_id, startup);
+       case RTM_NEWQDISC:
+       case RTM_DELQDISC:
+               return netlink_qdisc_change(h, ns_id, startup);
+       case RTM_NEWTCLASS:
+       case RTM_DELTCLASS:
+               return netlink_tclass_change(h, ns_id, startup);
+       case RTM_NEWTFILTER:
+       case RTM_DELTFILTER:
+               return netlink_tfilter_change(h, ns_id, startup);
+       case RTM_NEWVLAN:
+               return netlink_vlan_change(h, ns_id, startup);
+       case RTM_DELVLAN:
+               return netlink_vlan_change(h, ns_id, startup);
 
        /* Messages handled in the dplane thread */
        case RTM_NEWADDR:
@@ -481,9 +482,9 @@ static int dplane_netlink_information_fetch(struct nlmsghdr *h, ns_id_t ns_id,
        return 0;
 }
 
-static void kernel_read(struct thread *thread)
+static void kernel_read(struct event *thread)
 {
-       struct zebra_ns *zns = (struct zebra_ns *)THREAD_ARG(thread);
+       struct zebra_ns *zns = (struct zebra_ns *)EVENT_ARG(thread);
        struct zebra_dplane_info dp_info;
 
        /* Capture key info from ns struct */
@@ -492,8 +493,8 @@ static void kernel_read(struct thread *thread)
        netlink_parse_info(netlink_information_fetch, &zns->netlink, &dp_info,
                           5, false);
 
-       thread_add_read(zrouter.master, kernel_read, zns, zns->netlink.sock,
-                       &zns->t_netlink);
+       event_add_read(zrouter.master, kernel_read, zns, zns->netlink.sock,
+                      &zns->t_netlink);
 }
 
 /*
@@ -696,6 +697,12 @@ bool nl_attr_put32(struct nlmsghdr *n, unsigned int maxlen, int type,
        return nl_attr_put(n, maxlen, type, &data, sizeof(uint32_t));
 }
 
+bool nl_attr_put64(struct nlmsghdr *n, unsigned int maxlen, int type,
+                  uint64_t data)
+{
+       return nl_attr_put(n, maxlen, type, &data, sizeof(uint64_t));
+}
+
 struct rtattr *nl_attr_nest(struct nlmsghdr *n, unsigned int maxlen, int type)
 {
        struct rtattr *nest = NLMSG_TAIL(n);
@@ -1071,7 +1078,8 @@ static int netlink_parse_error(const struct nlsock *nl, struct nlmsghdr *h,
                                   nl_msg_type_to_str(msg_type), msg_type,
                                   err->msg.nlmsg_seq, err->msg.nlmsg_pid);
        } else {
-               if ((msg_type != RTM_GETNEXTHOP) || !startup)
+               if ((msg_type != RTM_GETNEXTHOP && msg_type != RTM_GETVLAN) ||
+                   !startup)
                        flog_err(EC_ZEBRA_UNEXPECTED_MESSAGE,
                                 "%s error: %s, type=%s(%u), seq=%u, pid=%u",
                                 nl->name, safe_strerror(-errnum),
@@ -1437,10 +1445,11 @@ static void nl_batch_reset(struct nl_batch *bth)
        bth->msgcnt = 0;
        bth->zns = NULL;
 
-       TAILQ_INIT(&(bth->ctx_list));
+       dplane_ctx_q_init(&(bth->ctx_list));
 }
 
-static void nl_batch_init(struct nl_batch *bth, struct dplane_ctx_q *ctx_out_q)
+static void nl_batch_init(struct nl_batch *bth,
+                         struct dplane_ctx_list_head *ctx_out_q)
 {
        /*
         * If the size of the buffer has changed, free and then allocate a new
@@ -1640,23 +1649,30 @@ static enum netlink_msg_status nl_put_msg(struct nl_batch *bth,
        case DPLANE_OP_INTF_DELETE:
                return netlink_put_intf_update_msg(bth, ctx);
 
-       case DPLANE_OP_TC_INSTALL:
-       case DPLANE_OP_TC_UPDATE:
-       case DPLANE_OP_TC_DELETE:
-               return netlink_put_tc_update_msg(bth, ctx);
+       case DPLANE_OP_TC_QDISC_INSTALL:
+       case DPLANE_OP_TC_QDISC_UNINSTALL:
+               return netlink_put_tc_qdisc_update_msg(bth, ctx);
+       case DPLANE_OP_TC_CLASS_ADD:
+       case DPLANE_OP_TC_CLASS_DELETE:
+       case DPLANE_OP_TC_CLASS_UPDATE:
+               return netlink_put_tc_class_update_msg(bth, ctx);
+       case DPLANE_OP_TC_FILTER_ADD:
+       case DPLANE_OP_TC_FILTER_DELETE:
+       case DPLANE_OP_TC_FILTER_UPDATE:
+               return netlink_put_tc_filter_update_msg(bth, ctx);
        }
 
        return FRR_NETLINK_ERROR;
 }
 
-void kernel_update_multi(struct dplane_ctx_q *ctx_list)
+void kernel_update_multi(struct dplane_ctx_list_head *ctx_list)
 {
        struct nl_batch batch;
        struct zebra_dplane_ctx *ctx;
-       struct dplane_ctx_q handled_list;
+       struct dplane_ctx_list_head handled_list;
        enum netlink_msg_status res;
 
-       TAILQ_INIT(&handled_list);
+       dplane_ctx_q_init(&handled_list);
        nl_batch_init(&batch, &handled_list);
 
        while (true) {
@@ -1687,7 +1703,7 @@ void kernel_update_multi(struct dplane_ctx_q *ctx_list)
 
        nl_batch_send(&batch);
 
-       TAILQ_INIT(ctx_list);
+       dplane_ctx_q_init(ctx_list);
        dplane_ctx_list_append(ctx_list, &handled_list);
 }
 
@@ -1744,7 +1760,7 @@ void kernel_init(struct zebra_ns *zns)
 {
        uint32_t groups, dplane_groups, ext_groups;
 #if defined SOL_NETLINK
-       int one, ret;
+       int one, ret, grp;
 #endif
 
        /*
@@ -1755,17 +1771,23 @@ void kernel_init(struct zebra_ns *zns)
         * keeping track of all the different values would
         * lead to confusion, so we need to convert the
         * RTNLGRP_XXX to a bit position for ourself
+        *
+        *
+        * NOTE: If the bit is >= 32, you must use setsockopt(). Those
+        * groups are added further below after SOL_NETLINK is verified to
+        * exist.
         */
        groups = RTMGRP_LINK                   |
-               RTMGRP_IPV4_ROUTE              |
-               RTMGRP_IPV4_IFADDR             |
-               RTMGRP_IPV6_ROUTE              |
-               RTMGRP_IPV6_IFADDR             |
-               RTMGRP_IPV4_MROUTE             |
-               RTMGRP_NEIGH                   |
-               ((uint32_t) 1 << (RTNLGRP_IPV4_RULE - 1)) |
-               ((uint32_t) 1 << (RTNLGRP_IPV6_RULE - 1)) |
-               ((uint32_t) 1 << (RTNLGRP_NEXTHOP - 1));
+                       RTMGRP_IPV4_ROUTE              |
+                       RTMGRP_IPV4_IFADDR             |
+                       RTMGRP_IPV6_ROUTE              |
+                       RTMGRP_IPV6_IFADDR             |
+                       RTMGRP_IPV4_MROUTE             |
+                       RTMGRP_NEIGH                   |
+                       ((uint32_t) 1 << (RTNLGRP_IPV4_RULE - 1)) |
+                       ((uint32_t) 1 << (RTNLGRP_IPV6_RULE - 1)) |
+                       ((uint32_t) 1 << (RTNLGRP_NEXTHOP - 1))   |
+                       ((uint32_t) 1 << (RTNLGRP_TC - 1));
 
        dplane_groups = (RTMGRP_LINK            |
                         RTMGRP_IPV4_IFADDR     |
@@ -1833,6 +1855,18 @@ void kernel_init(struct zebra_ns *zns)
         * sure that we want to pull into our build system.
         */
 #if defined SOL_NETLINK
+
+       /*
+        * setsockopt multicast group subscriptions that don't fit in nl_groups
+        */
+       grp = RTNLGRP_BRVLAN;
+       ret = setsockopt(zns->netlink.sock, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP,
+                        &grp, sizeof(grp));
+
+       if (ret < 0)
+               zlog_notice(
+                       "Registration for RTNLGRP_BRVLAN Membership failed : %d %s",
+                       errno, safe_strerror(errno));
        /*
         * Let's tell the kernel that we want to receive extended
         * ACKS over our command socket(s)
@@ -1905,8 +1939,8 @@ void kernel_init(struct zebra_ns *zns)
 
        zns->t_netlink = NULL;
 
-       thread_add_read(zrouter.master, kernel_read, zns,
-                       zns->netlink.sock, &zns->t_netlink);
+       event_add_read(zrouter.master, kernel_read, zns, zns->netlink.sock,
+                      &zns->t_netlink);
 
        rt_netlink_init();
 }
@@ -1925,7 +1959,7 @@ static void kernel_nlsock_fini(struct nlsock *nls)
 
 void kernel_terminate(struct zebra_ns *zns, bool complete)
 {
-       THREAD_OFF(zns->t_netlink);
+       EVENT_OFF(zns->t_netlink);
 
        kernel_nlsock_fini(&zns->netlink);