This diff implements 'bgpctl show flowspec' and on top of that also
'bgpctl flowspec flush'.  bgpctl now uses both util.c and flowspec.c from
bgpd. The code to print flowspec is stolen from printconf.c and I did not
implement the json output yet because I have not decided on how to dump
the NLRI there.

-- 
:wq Claudio

Index: Makefile
===================================================================
RCS file: /cvs/src/usr.sbin/bgpctl/Makefile,v
retrieving revision 1.18
diff -u -p -r1.18 Makefile
--- Makefile    17 Oct 2022 12:01:19 -0000      1.18
+++ Makefile    20 Apr 2023 12:55:28 -0000
@@ -4,7 +4,8 @@
 
 PROG=  bgpctl
 SRCS=  bgpctl.c output.c output_json.c output_ometric.c parser.c \
-       mrtparser.c util.c json.c ometric.c
+       mrtparser.c json.c ometric.c
+SRCS+= util.c flowspec.c
 CFLAGS+= -Wall
 CFLAGS+= -Wstrict-prototypes -Wmissing-prototypes
 CFLAGS+= -Wmissing-declarations
Index: bgpctl.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpctl/bgpctl.c,v
retrieving revision 1.290
diff -u -p -r1.290 bgpctl.c
--- bgpctl.c    13 Mar 2023 16:59:22 -0000      1.290
+++ bgpctl.c    20 Apr 2023 12:55:28 -0000
@@ -361,6 +361,22 @@ main(int argc, char *argv[])
                mrt_parse(res->mrtfd, &net_mrt, 1);
                done = 1;
                break;
+       case FLOWSPEC_ADD:
+       case FLOWSPEC_REMOVE:
+               done = 1;
+               break;
+       case FLOWSPEC_FLUSH:
+               imsg_compose(ibuf, IMSG_FLOWSPEC_FLUSH, 0, 0, -1, NULL, 0);
+               printf("request sent.\n");
+               done = 1;
+               break;
+       case FLOWSPEC_SHOW:
+               memset(&ribreq, 0, sizeof(ribreq));
+               ribreq.aid = res->aid;
+               strlcpy(ribreq.rib, res->rib, sizeof(ribreq.rib));
+               imsg_compose(ibuf, IMSG_CTL_SHOW_FLOWSPEC, 0, 0, -1,
+                   &ribreq, sizeof(ribreq));
+               break;
        case LOG_VERBOSE:
                verbose = 1;
                /* FALLTHROUGH */
@@ -424,6 +440,7 @@ show(struct imsg *imsg, struct parse_res
        struct ctl_show_rtr      rtr;
        struct kroute_full      *kf;
        struct ktable           *kt;
+       struct flowspec         *f;
        struct ctl_show_rib      rib;
        struct rde_memstats      stats;
        u_char                  *asdata;
@@ -466,6 +483,14 @@ show(struct imsg *imsg, struct parse_res
                        break;
                kf = imsg->data;
                output->fib(kf);
+               break;
+       case IMSG_CTL_SHOW_FLOWSPEC:
+               if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(*f))
+                       errx(1, "wrong imsg len");
+               if (output->flowspec == NULL)
+                       break;
+               f = imsg->data;
+               output->flowspec(f);
                break;
        case IMSG_CTL_SHOW_FIB_TABLES:
                if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(*kt))
Index: bgpctl.h
===================================================================
RCS file: /cvs/src/usr.sbin/bgpctl/bgpctl.h,v
retrieving revision 1.20
diff -u -p -r1.20 bgpctl.h
--- bgpctl.h    28 Mar 2023 12:07:09 -0000      1.20
+++ bgpctl.h    20 Apr 2023 12:55:28 -0000
@@ -24,6 +24,7 @@ struct output {
        void    (*timer)(struct ctl_timer *);
        void    (*fib)(struct kroute_full *);
        void    (*fib_table)(struct ktable *);
+       void    (*flowspec)(struct flowspec *);
        void    (*nexthop)(struct ctl_show_nexthop *);
        void    (*interface)(struct ctl_show_interface *);
        void    (*attr)(u_char *, size_t, int, int);
Index: output.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpctl/output.c,v
retrieving revision 1.38
diff -u -p -r1.38 output.c
--- output.c    28 Mar 2023 12:07:09 -0000      1.38
+++ output.c    20 Apr 2023 12:55:28 -0000
@@ -85,6 +85,8 @@ show_head(struct parse_result *res)
                printf("%-5s %-4s %-32s %-32s\n", "flags", "prio",
                    "destination", "gateway");
                break;
+       case FLOWSPEC_SHOW:
+               printf("flags: S = Static\n");
        default:
                break;
        }
@@ -493,6 +495,108 @@ show_fib_table(struct ktable *kt)
 }
 
 static void
+print_flowspec_list(struct flowspec *f, int type, int is_v6)
+{
+       const uint8_t *comp;
+       const char *fmt;
+       int complen, off = 0;
+
+       if (flowspec_get_component(f->data, f->len, type, is_v6,
+           &comp, &complen) != 1)
+               return;
+
+       printf("%s ", flowspec_fmt_label(type));
+       fmt = flowspec_fmt_num_op(comp, complen, &off);
+       if (off == -1) {
+               printf("%s ", fmt);
+       } else {
+               printf("{ %s ", fmt);
+               do {
+                       fmt = flowspec_fmt_num_op(comp, complen, &off);
+                       printf("%s ", fmt);
+               } while (off != -1);
+               printf("} ");
+       }
+}
+
+static void
+print_flowspec_flags(struct flowspec *f, int type, int is_v6)
+{
+       const uint8_t *comp;
+       const char *fmt, *flags;
+       int complen, off = 0;
+
+       if (flowspec_get_component(f->data, f->len, type, is_v6,
+           &comp, &complen) != 1)
+               return;
+
+       printf("%s ", flowspec_fmt_label(type));
+
+       switch (type) {
+       case FLOWSPEC_TYPE_TCP_FLAGS:
+               flags = FLOWSPEC_TCP_FLAG_STRING;
+               break;
+       case FLOWSPEC_TYPE_FRAG:
+               if (!is_v6)
+                       flags = FLOWSPEC_FRAG_STRING4;
+               else
+                       flags = FLOWSPEC_FRAG_STRING6;
+               break;
+       }
+
+       fmt = flowspec_fmt_bin_op(comp, complen, &off, flags);
+       if (off == -1) {
+               printf("%s ", fmt);
+       } else {
+               printf("{ %s ", fmt);
+               do {
+                       fmt = flowspec_fmt_bin_op(comp, complen, &off, flags);
+                       printf("%s ", fmt);
+               } while (off != -1);
+               printf("} ");
+       }
+}
+
+static void
+print_flowspec_addr(struct flowspec *f, int type, int is_v6)
+{
+       struct bgpd_addr addr;
+       uint8_t plen;
+
+       flowspec_get_addr(f->data, f->len, type, is_v6, &addr, &plen, NULL);
+       if (plen == 0)
+               printf("%s any ", flowspec_fmt_label(type));
+       else
+               printf("%s %s/%u ", flowspec_fmt_label(type),
+                   log_addr(&addr), plen);
+}
+
+static void
+show_flowspec(struct flowspec *f)
+{
+       int is_v6 = (f->aid == AID_FLOWSPECv6);
+
+       printf("%-5s ", fmt_fib_flags(f->flags));
+       print_flowspec_list(f, FLOWSPEC_TYPE_PROTO, is_v6);
+
+       print_flowspec_addr(f, FLOWSPEC_TYPE_SOURCE, is_v6);
+       print_flowspec_list(f, FLOWSPEC_TYPE_SRC_PORT, is_v6);
+
+       print_flowspec_addr(f, FLOWSPEC_TYPE_DEST, is_v6);
+       print_flowspec_list(f, FLOWSPEC_TYPE_DST_PORT, is_v6);
+
+       print_flowspec_list(f, FLOWSPEC_TYPE_DSCP, is_v6);
+       print_flowspec_list(f, FLOWSPEC_TYPE_PKT_LEN, is_v6);
+       print_flowspec_flags(f, FLOWSPEC_TYPE_TCP_FLAGS, is_v6);
+       print_flowspec_flags(f, FLOWSPEC_TYPE_FRAG, is_v6);
+       /* TODO: fixup the code handling to be like in the parser */
+       print_flowspec_list(f, FLOWSPEC_TYPE_ICMP_TYPE, is_v6);
+       print_flowspec_list(f, FLOWSPEC_TYPE_ICMP_CODE, is_v6);
+
+       printf("\n");
+}
+
+static void
 show_nexthop(struct ctl_show_nexthop *nh)
 {
        char            *s;
@@ -1117,6 +1221,7 @@ const struct output show_output = {
        .timer = show_timer,
        .fib = show_fib,
        .fib_table = show_fib_table,
+       .flowspec = show_flowspec,
        .nexthop = show_nexthop,
        .interface = show_interface,
        .communities = show_communities,
Index: parser.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpctl/parser.c,v
retrieving revision 1.129
diff -u -p -r1.129 parser.c
--- parser.c    17 Apr 2023 13:48:31 -0000      1.129
+++ parser.c    20 Apr 2023 12:55:40 -0000
@@ -96,6 +96,7 @@ static const struct token t_show_mrt_as[
 static const struct token t_show_prefix[];
 static const struct token t_show_ip[];
 static const struct token t_network[];
+static const struct token t_flowspec[];
 static const struct token t_bulk[];
 static const struct token t_network_show[];
 static const struct token t_prefix[];
@@ -107,6 +108,7 @@ static const struct token t_communicatio
 
 static const struct token t_main[] = {
        { KEYWORD,      "fib",          FIB,            t_fib},
+       { KEYWORD,      "flowspec",     NONE,           t_flowspec},
        { KEYWORD,      "log",          NONE,           t_log},
        { KEYWORD,      "neighbor",     NEIGHBOR,       t_neighbor},
        { KEYWORD,      "network",      NONE,           t_network},
@@ -118,6 +120,7 @@ static const struct token t_main[] = {
 static const struct token t_show[] = {
        { NOTOKEN,      "",             NONE,           NULL},
        { KEYWORD,      "fib",          SHOW_FIB,       t_show_fib},
+       { KEYWORD,      "flowspec",     FLOWSPEC_SHOW,  t_network_show},
        { KEYWORD,      "interfaces",   SHOW_INTERFACE, NULL},
        { KEYWORD,      "ip",           NONE,           t_show_ip},
        { KEYWORD,      "metrics",      SHOW_METRICS,   NULL},
@@ -326,6 +329,12 @@ static const struct token t_network[] = 
        { KEYWORD,      "flush",        NETWORK_FLUSH,  NULL},
        { KEYWORD,      "mrt",          NETWORK_MRT,    t_show_mrt},
        { KEYWORD,      "show",         NETWORK_SHOW,   t_network_show},
+       { ENDTOKEN,     "",             NONE,           NULL}
+};
+
+static const struct token t_flowspec[] = {
+       { KEYWORD,      "flush",        FLOWSPEC_FLUSH, NULL},
+       { KEYWORD,      "show",         FLOWSPEC_SHOW,  t_network_show},
        { ENDTOKEN,     "",             NONE,           NULL}
 };
 
Index: parser.h
===================================================================
RCS file: /cvs/src/usr.sbin/bgpctl/parser.h,v
retrieving revision 1.44
diff -u -p -r1.44 parser.h
--- parser.h    17 Oct 2022 16:51:36 -0000      1.44
+++ parser.h    20 Apr 2023 12:55:28 -0000
@@ -56,7 +56,11 @@ enum actions {
        NETWORK_SHOW,
        NETWORK_MRT,
        NETWORK_BULK_ADD,
-       NETWORK_BULK_REMOVE
+       NETWORK_BULK_REMOVE,
+       FLOWSPEC_ADD,
+       FLOWSPEC_REMOVE,
+       FLOWSPEC_FLUSH,
+       FLOWSPEC_SHOW,
 };
 
 struct parse_result {

Reply via email to