iproute2/ip/ipila.c
<<
>>
Prefs
   1/*
   2 * ipila.c      ILA (Identifier Locator Addressing) support
   3 *
   4 *              This program is free software; you can redistribute it and/or
   5 *              modify it under the terms of the GNU General Public License
   6 *              as published by the Free Software Foundation; either version
   7 *              2 of the License, or (at your option) any later version.
   8 *
   9 * Authors:     Tom Herbert <tom@herbertland.com>
  10 */
  11
  12#include <netdb.h>
  13#include <stdio.h>
  14#include <stdlib.h>
  15#include <string.h>
  16#include <net/if.h>
  17#include <linux/ila.h>
  18#include <linux/genetlink.h>
  19#include <linux/ip.h>
  20#include <arpa/inet.h>
  21
  22#include "libgenl.h"
  23#include "utils.h"
  24#include "ip_common.h"
  25#include "ila_common.h"
  26#include "json_print.h"
  27
  28static void usage(void)
  29{
  30        fprintf(stderr,
  31                "Usage: ip ila add loc_match LOCATOR_MATCH loc LOCATOR [ dev DEV ] OPTIONS\n"
  32                "       ip ila del loc_match LOCATOR_MATCH [ loc LOCATOR ] [ dev DEV ]\n"
  33                "       ip ila list\n"
  34                "OPTIONS := [ csum-mode { adj-transport | neutral-map |\n"
  35                "                         neutral-map-auto | no-action } ]\n"
  36                "           [ ident-type { luid | use-format } ]\n");
  37
  38        exit(-1);
  39}
  40
  41/* netlink socket */
  42static struct rtnl_handle genl_rth = { .fd = -1 };
  43static int genl_family = -1;
  44
  45#define ILA_REQUEST(_req, _bufsiz, _cmd, _flags)        \
  46        GENL_REQUEST(_req, _bufsiz, genl_family, 0,     \
  47                     ILA_GENL_VERSION, _cmd, _flags)
  48
  49#define ILA_RTA(g) ((struct rtattr *)(((char *)(g)) +   \
  50        NLMSG_ALIGN(sizeof(struct genlmsghdr))))
  51
  52static void print_addr64(__u64 addr, char *buff, size_t len)
  53{
  54        __u16 *words = (__u16 *)&addr;
  55        __u16 v;
  56        int i, ret;
  57        size_t written = 0;
  58        char *sep = ":";
  59
  60        for (i = 0; i < 4; i++) {
  61                v = ntohs(words[i]);
  62
  63                if (i == 3)
  64                        sep = "";
  65
  66                ret = snprintf(&buff[written], len - written, "%x%s", v, sep);
  67                written += ret;
  68        }
  69}
  70
  71static void print_ila_locid(const char *tag, int attr, struct rtattr *tb[])
  72{
  73        char abuf[256];
  74
  75        if (tb[attr])
  76                print_addr64(rta_getattr_u64(tb[attr]),
  77                             abuf, sizeof(abuf));
  78        else
  79                snprintf(abuf, sizeof(abuf), "-");
  80
  81        /* 20 = sizeof("xxxx:xxxx:xxxx:xxxx") */
  82        print_string(PRINT_ANY, tag, "%-20s", abuf);
  83}
  84
  85static int print_ila_mapping(struct nlmsghdr *n, void *arg)
  86{
  87        struct genlmsghdr *ghdr;
  88        struct rtattr *tb[ILA_ATTR_MAX + 1];
  89        int len = n->nlmsg_len;
  90
  91        if (n->nlmsg_type != genl_family)
  92                return 0;
  93
  94        len -= NLMSG_LENGTH(GENL_HDRLEN);
  95        if (len < 0)
  96                return -1;
  97
  98        ghdr = NLMSG_DATA(n);
  99        parse_rtattr(tb, ILA_ATTR_MAX, (void *) ghdr + GENL_HDRLEN, len);
 100
 101        open_json_object(NULL);
 102        print_ila_locid("locator_match", ILA_ATTR_LOCATOR_MATCH, tb);
 103        print_ila_locid("locator", ILA_ATTR_LOCATOR, tb);
 104
 105        if (tb[ILA_ATTR_IFINDEX]) {
 106                __u32 ifindex
 107                        = rta_getattr_u32(tb[ILA_ATTR_IFINDEX]);
 108
 109                print_color_string(PRINT_ANY, COLOR_IFNAME,
 110                                   "interface", "%-16s",
 111                                   ll_index_to_name(ifindex));
 112        } else {
 113                print_string(PRINT_FP, NULL, "%-10s ", "-");
 114        }
 115
 116        if (tb[ILA_ATTR_CSUM_MODE]) {
 117                __u8 csum = rta_getattr_u8(tb[ILA_ATTR_CSUM_MODE]);
 118
 119                print_string(PRINT_ANY, "csum_mode", "%s",
 120                             ila_csum_mode2name(csum));
 121        } else
 122                print_string(PRINT_FP, NULL, "%-10s ", "-");
 123
 124        if (tb[ILA_ATTR_IDENT_TYPE])
 125                print_string(PRINT_ANY, "ident_type", "%s",
 126                        ila_ident_type2name(rta_getattr_u8(
 127                                                tb[ILA_ATTR_IDENT_TYPE])));
 128        else
 129                print_string(PRINT_FP, NULL, "%s", "-");
 130
 131        print_nl();
 132        close_json_object();
 133
 134        return 0;
 135}
 136
 137#define NLMSG_BUF_SIZE 4096
 138
 139static int do_list(int argc, char **argv)
 140{
 141        ILA_REQUEST(req, 1024, ILA_CMD_GET, NLM_F_REQUEST | NLM_F_DUMP);
 142
 143        if (argc > 0) {
 144                fprintf(stderr, "\"ip ila show\" does not take "
 145                        "any arguments.\n");
 146                return -1;
 147        }
 148
 149        if (rtnl_send(&genl_rth, (void *)&req, req.n.nlmsg_len) < 0) {
 150                perror("Cannot send dump request");
 151                exit(1);
 152        }
 153
 154        new_json_obj(json);
 155        if (rtnl_dump_filter(&genl_rth, print_ila_mapping, stdout) < 0) {
 156                fprintf(stderr, "Dump terminated\n");
 157                return 1;
 158        }
 159        delete_json_obj();
 160        fflush(stdout);
 161
 162        return 0;
 163}
 164
 165static int ila_parse_opt(int argc, char **argv, struct nlmsghdr *n,
 166                         bool adding)
 167{
 168        __u64 locator = 0;
 169        __u64 locator_match = 0;
 170        int ifindex = 0;
 171        int csum_mode = 0;
 172        int ident_type = 0;
 173        bool loc_set = false;
 174        bool loc_match_set = false;
 175        bool ifindex_set = false;
 176        bool csum_mode_set = false;
 177        bool ident_type_set = false;
 178
 179        while (argc > 0) {
 180                if (!matches(*argv, "loc")) {
 181                        NEXT_ARG();
 182
 183                        if (get_addr64(&locator, *argv) < 0) {
 184                                fprintf(stderr, "Bad locator: %s\n", *argv);
 185                                return -1;
 186                        }
 187                        loc_set = true;
 188                } else if (!matches(*argv, "loc_match")) {
 189                        NEXT_ARG();
 190
 191                        if (get_addr64(&locator_match, *argv) < 0) {
 192                                fprintf(stderr, "Bad locator to match: %s\n",
 193                                        *argv);
 194                                return -1;
 195                        }
 196                        loc_match_set = true;
 197                } else if (!matches(*argv, "csum-mode")) {
 198                        NEXT_ARG();
 199
 200                        csum_mode = ila_csum_name2mode(*argv);
 201                        if (csum_mode < 0) {
 202                                fprintf(stderr, "Bad csum-mode: %s\n",
 203                                        *argv);
 204                                return -1;
 205                        }
 206                        csum_mode_set = true;
 207                } else if (!matches(*argv, "ident-type")) {
 208                        NEXT_ARG();
 209
 210                        ident_type = ila_ident_name2type(*argv);
 211                        if (ident_type < 0) {
 212                                fprintf(stderr, "Bad ident-type: %s\n",
 213                                        *argv);
 214                                return -1;
 215                        }
 216                        ident_type_set = true;
 217                } else if (!matches(*argv, "dev")) {
 218                        NEXT_ARG();
 219
 220                        ifindex = ll_name_to_index(*argv);
 221                        if (ifindex == 0) {
 222                                fprintf(stderr, "No such interface: %s\n",
 223                                        *argv);
 224                                return -1;
 225                        }
 226                        ifindex_set = true;
 227                } else {
 228                        usage();
 229                        return -1;
 230                }
 231                argc--, argv++;
 232        }
 233
 234        if (adding) {
 235                if (!loc_set) {
 236                        fprintf(stderr, "ila: missing locator\n");
 237                        return -1;
 238                }
 239                if (!loc_match_set) {
 240                        fprintf(stderr, "ila: missing locator0match\n");
 241                        return -1;
 242                }
 243        }
 244
 245        if (loc_match_set)
 246                addattr64(n, 1024, ILA_ATTR_LOCATOR_MATCH, locator_match);
 247
 248        if (loc_set)
 249                addattr64(n, 1024, ILA_ATTR_LOCATOR, locator);
 250
 251        if (ifindex_set)
 252                addattr32(n, 1024, ILA_ATTR_IFINDEX, ifindex);
 253
 254        if (csum_mode_set)
 255                addattr8(n, 1024, ILA_ATTR_CSUM_MODE, csum_mode);
 256
 257        if (ident_type_set)
 258                addattr8(n, 1024, ILA_ATTR_IDENT_TYPE, ident_type);
 259
 260        return 0;
 261}
 262
 263static int do_add(int argc, char **argv)
 264{
 265        ILA_REQUEST(req, 1024, ILA_CMD_ADD, NLM_F_REQUEST);
 266
 267        ila_parse_opt(argc, argv, &req.n, true);
 268
 269        if (rtnl_talk(&genl_rth, &req.n, NULL) < 0)
 270                return -2;
 271
 272        return 0;
 273}
 274
 275static int do_del(int argc, char **argv)
 276{
 277        ILA_REQUEST(req, 1024, ILA_CMD_DEL, NLM_F_REQUEST);
 278
 279        ila_parse_opt(argc, argv, &req.n, false);
 280
 281        if (rtnl_talk(&genl_rth, &req.n, NULL) < 0)
 282                return -2;
 283
 284        return 0;
 285}
 286
 287int do_ipila(int argc, char **argv)
 288{
 289        if (argc < 1)
 290                usage();
 291
 292        if (matches(*argv, "help") == 0)
 293                usage();
 294
 295        if (genl_init_handle(&genl_rth, ILA_GENL_NAME, &genl_family))
 296                exit(1);
 297
 298        if (matches(*argv, "add") == 0)
 299                return do_add(argc-1, argv+1);
 300        if (matches(*argv, "delete") == 0)
 301                return do_del(argc-1, argv+1);
 302        if (matches(*argv, "list") == 0)
 303                return do_list(argc-1, argv+1);
 304
 305        fprintf(stderr, "Command \"%s\" is unknown, try \"ip ila help\".\n",
 306                *argv);
 307        exit(-1);
 308}
 309