[ovs-dev] [1/2] utilities/nlmon: extend nlmon design to handle more groups

Mohammad Heib mheib at redhat.com
Sun Nov 21 23:39:32 UTC 2021


Extend nlmon design to be easier to add and monitor new
Netlink groups.

This patch converts nlmon code to be more generic and easier
to add and specify which netlink groups users want to monitor
using command line.

This change is backward compatible and apps that use nlmon
can still use it without any change required.

Signed-off-by: Mohammad Heib <mheib at redhat.com>
---
 utilities/nlmon.c | 130 ++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 120 insertions(+), 10 deletions(-)

diff --git a/utilities/nlmon.c b/utilities/nlmon.c
index 32aa948c6..c2f232a12 100644
--- a/utilities/nlmon.c
+++ b/utilities/nlmon.c
@@ -23,6 +23,7 @@
 #include <sys/uio.h>
 #include <stddef.h>
 #include <linux/rtnetlink.h>
+#include <getopt.h>
 #include "netlink.h"
 #include "netlink-socket.h"
 #include "netnsid.h"
@@ -32,34 +33,116 @@
 #include "util.h"
 #include "openvswitch/vlog.h"
 
+#define MAX_TYPE_LEN 25
+
+typedef int (*GRP_handler)(void *);
+
 static const struct nl_policy rtnlgrp_link_policy[] = {
     [IFLA_IFNAME] = { .type = NL_A_STRING, .optional = false },
     [IFLA_MASTER] = { .type = NL_A_U32, .optional = true },
 };
 
+int nlmon_link(void *);
+int nlmon_tc(void *);
+
+static void print_usage(void);
+
+static const struct {
+    enum rtnetlink_groups gr_id;
+    const char * gr_name;
+    GRP_handler handler;
+} known_groups[] = {
+    { RTNLGRP_LINK, "link", nlmon_link},
+    { RTNLGRP_TC, "tc", nlmon_tc},
+    /* keep new groups above */
+    { RTNLGRP_NONE, NULL, NULL }
+};
+
 int
-main(int argc OVS_UNUSED, char *argv[])
+main(int argc, char *argv[])
 {
-    uint64_t buf_stub[4096 / 64];
-    struct nl_sock *sock;
-    int nsid;
-    struct ofpbuf buf;
-    int error;
+
+    char type[MAX_TYPE_LEN];
+    int rc;
+    enum rtnetlink_groups gr_id = RTNLGRP_LINK;
+    enum vlog_level level = VLL_DBG;
 
     set_program_name(argv[0]);
-    vlog_set_levels(NULL, VLF_ANY_DESTINATION, VLL_DBG);
 
-    error = nl_sock_create(NETLINK_ROUTE, &sock);
+    for (;;) {
+        int c, optidx = 0;
+        static struct option long_opts[] = {
+                { "type", 1, 0, 't' },
+                { "log-level", 1, 0, 'l' },
+                { "help", 0, 0, 'h' },
+                { 0, 0, 0, 0 }
+        };
+
+        c = getopt_long(argc, argv, "t:l:h", long_opts, &optidx);
+        if (c == -1) {
+            break;
+        }
+
+        switch (c) {
+        case 't':
+            ovs_strzcpy(type, optarg, MAX_TYPE_LEN - 1);
+            break;
+        case 'l':
+            if (strcmp("info", optarg) == 0) {
+                level = VLL_INFO;
+            } else if (strcmp("err", optarg) == 0) {
+                level = VLL_ERR;
+            }
+            break;
+        default:
+            print_usage();
+            break;
+        }
+    }
+
+    vlog_set_levels(NULL, VLF_ANY_DESTINATION, level);
+
+    for (int i = 0; known_groups[i].gr_id != RTNLGRP_NONE; i++) {
+        if (strcmp(type, known_groups[i].gr_name) == 0) {
+            gr_id = known_groups[i].gr_id;
+            rc = known_groups[i].handler(&gr_id);
+            goto out;
+        }
+    }
+
+    /* no group found call default group */
+    rc = nlmon_link(&gr_id);
+
+out:
+    return rc;
+}
+
+static void
+init_socket(struct nl_sock **sk, enum rtnetlink_groups *gid)
+{
+    int error;
+
+    error = nl_sock_create(NETLINK_ROUTE, sk);
     if (error) {
         ovs_fatal(error, "could not create rtnetlink socket");
     }
 
-    error = nl_sock_join_mcgroup(sock, RTNLGRP_LINK);
+    error = nl_sock_join_mcgroup(*sk, *gid);
     if (error) {
         ovs_fatal(error, "could not join RTNLGRP_LINK multicast group");
     }
+    nl_sock_listen_all_nsid(*sk, true);
+}
 
-    nl_sock_listen_all_nsid(sock, true);
+int nlmon_link(void * args)
+{
+    uint64_t buf_stub[4096 / 64];
+    struct nl_sock *sock;
+    int nsid;
+    struct ofpbuf buf;
+    int error;
+
+    init_socket(&sock, (enum rtnetlink_groups *) args);
     ofpbuf_use_stub(&buf, buf_stub, sizeof buf_stub);
     for (;;) {
         error = nl_sock_recv(sock, &buf, &nsid, false);
@@ -146,3 +229,30 @@ main(int argc OVS_UNUSED, char *argv[])
     }
 }
 
+int nlmon_tc(void * args OVS_UNUSED)
+{
+    printf("not supported Will be added soon \n");
+    return ENOTSUP;
+}
+
+static void print_usage(void)
+{
+        int i;
+
+        printf(
+        "Usage: nlmon [OPTION] \n"
+        "\n"
+        "Options\n"
+        " -t, --type=group_type netlink group type\n"
+        " -l, --log-level={info,err,dbg} set output log level (Default dbg)\n"
+        " -h, --help            Show this help.\n"
+        "\n"
+        );
+        printf("Known groups(Default group - link):");
+        for (i = 0; known_groups[i].gr_id != RTNLGRP_NONE; i++) {
+            printf(" [%s],", known_groups[i].gr_name);
+        }
+        printf("\n");
+        exit(0);
+}
+
-- 
2.27.0



More information about the dev mailing list