iproute2/dcb/dcb_rewr.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2
   3#include <errno.h>
   4#include <linux/dcbnl.h>
   5#include <stdio.h>
   6
   7#include "dcb.h"
   8#include "utils.h"
   9
  10static void dcb_rewr_help_add(void)
  11{
  12        fprintf(stderr,
  13                "Usage: dcb rewr { add | del | replace } dev STRING\n"
  14                "           [ prio-pcp PRIO:PCP ]\n"
  15                "           [ prio-dscp PRIO:DSCP ]\n"
  16                "\n"
  17                " where PRIO := { 0 .. 7 }\n"
  18                "       PCP  := { 0(nd/de) .. 7(nd/de) }\n"
  19                "       DSCP := { 0 .. 63 }\n"
  20                "\n"
  21        );
  22}
  23
  24static void dcb_rewr_help_show_flush(void)
  25{
  26        fprintf(stderr,
  27                "Usage: dcb rewr { show | flush } dev STRING\n"
  28                "           [ prio-pcp ]\n"
  29                "           [ prio-dscp ]\n"
  30                "\n"
  31        );
  32}
  33
  34static void dcb_rewr_help(void)
  35{
  36        fprintf(stderr,
  37                "Usage: dcb rewr help\n"
  38                "\n"
  39        );
  40        dcb_rewr_help_show_flush();
  41        dcb_rewr_help_add();
  42}
  43
  44static void dcb_rewr_parse_mapping_cb(__u32 key, __u64 value, void *data)
  45{
  46        struct dcb_app_parse_mapping *pm = data;
  47        struct dcb_app app = {
  48                .selector = pm->selector,
  49                .priority = key,
  50                .protocol = value,
  51        };
  52
  53        if (pm->err)
  54                return;
  55
  56        pm->err = dcb_app_table_push(pm->tab, &app);
  57}
  58
  59static int dcb_rewr_parse_mapping_prio_pcp(__u32 key, char *value, void *data)
  60{
  61        __u32 pcp;
  62
  63        if (dcb_app_parse_pcp(&pcp, value))
  64                return -EINVAL;
  65
  66        return dcb_parse_mapping("PRIO", key, IEEE_8021QAZ_MAX_TCS - 1,
  67                                 "PCP", pcp, DCB_APP_PCP_MAX,
  68                                 dcb_rewr_parse_mapping_cb, data);
  69}
  70
  71static int dcb_rewr_parse_mapping_prio_dscp(__u32 key, char *value, void *data)
  72{
  73        __u32 dscp;
  74
  75        if (dcb_app_parse_dscp(&dscp, value))
  76                return -EINVAL;
  77
  78        return dcb_parse_mapping("PRIO", key, IEEE_8021QAZ_MAX_TCS - 1,
  79                                 "DSCP", dscp, DCB_APP_DSCP_MAX,
  80                                 dcb_rewr_parse_mapping_cb, data);
  81}
  82
  83static void dcb_rewr_print_prio_pid(int (*print_pid)(__u16 protocol),
  84                                    const struct dcb_app *app)
  85{
  86        print_uint(PRINT_ANY, NULL, "%u:", app->priority);
  87        print_pid(app->protocol);
  88}
  89
  90static void dcb_rewr_print_prio_pcp(const struct dcb *dcb,
  91                                    const struct dcb_app_table *tab)
  92{
  93        dcb_app_print_filtered(tab, dcb_app_is_pcp,
  94                               dcb_rewr_print_prio_pid,
  95                               dcb->numeric ? dcb_app_print_pid_dec :
  96                                              dcb_app_print_pid_pcp,
  97                               "prio_pcp", "prio-pcp");
  98}
  99
 100static void dcb_rewr_print_prio_dscp(const struct dcb *dcb,
 101                                     const struct dcb_app_table *tab)
 102{
 103        dcb_app_print_filtered(tab, dcb_app_is_dscp,
 104                               dcb_rewr_print_prio_pid,
 105                               dcb->numeric ? dcb_app_print_pid_dec :
 106                                              dcb_app_print_pid_dscp,
 107                               "prio_dscp", "prio-dscp");
 108}
 109
 110static void dcb_rewr_print(const struct dcb *dcb,
 111                           const struct dcb_app_table *tab)
 112{
 113        dcb_rewr_print_prio_pcp(dcb, tab);
 114        dcb_rewr_print_prio_dscp(dcb, tab);
 115}
 116
 117static bool dcb_rewr_prio_eq(const struct dcb_app *aa, const struct dcb_app *ab)
 118{
 119        return aa->selector == ab->selector &&
 120               aa->priority == ab->priority;
 121}
 122
 123static int dcb_cmd_rewr_parse_add_del(struct dcb *dcb, const char *dev,
 124                                      int argc, char **argv,
 125                                      struct dcb_app_table *tab)
 126{
 127        struct dcb_app_parse_mapping pm = {
 128                .tab = tab,
 129        };
 130        int ret;
 131
 132        if (!argc) {
 133                dcb_rewr_help_add();
 134                return 0;
 135        }
 136
 137        do {
 138                if (strcmp(*argv, "help") == 0) {
 139                        dcb_rewr_help_add();
 140                        return 0;
 141                } else if (strcmp(*argv, "prio-pcp") == 0) {
 142                        NEXT_ARG();
 143                        pm.selector = DCB_APP_SEL_PCP;
 144                        ret = parse_mapping(&argc, &argv, false,
 145                                            &dcb_rewr_parse_mapping_prio_pcp,
 146                                            &pm);
 147                } else if (strcmp(*argv, "prio-dscp") == 0) {
 148                        NEXT_ARG();
 149                        pm.selector = IEEE_8021QAZ_APP_SEL_DSCP;
 150                        ret = parse_mapping(&argc, &argv, false,
 151                                            &dcb_rewr_parse_mapping_prio_dscp,
 152                                            &pm);
 153                } else {
 154                        fprintf(stderr, "What is \"%s\"?\n", *argv);
 155                        dcb_rewr_help_add();
 156                        return -EINVAL;
 157                }
 158
 159                if (ret != 0) {
 160                        fprintf(stderr, "Invalid mapping %s\n", *argv);
 161                        return ret;
 162                }
 163                if (pm.err)
 164                        return pm.err;
 165        } while (argc > 0);
 166
 167        return 0;
 168}
 169
 170static int dcb_cmd_rewr_add(struct dcb *dcb, const char *dev, int argc,
 171                            char **argv)
 172{
 173        struct dcb_app_table tab = { .attr = DCB_ATTR_DCB_REWR_TABLE };
 174        int ret;
 175
 176        ret = dcb_cmd_rewr_parse_add_del(dcb, dev, argc, argv, &tab);
 177        if (ret != 0)
 178                return ret;
 179
 180        ret = dcb_app_add_del(dcb, dev, DCB_CMD_IEEE_SET, &tab, NULL);
 181        dcb_app_table_fini(&tab);
 182        return ret;
 183}
 184
 185static int dcb_cmd_rewr_del(struct dcb *dcb, const char *dev, int argc,
 186                            char **argv)
 187{
 188        struct dcb_app_table tab = { .attr = DCB_ATTR_DCB_REWR_TABLE };
 189        int ret;
 190
 191        ret = dcb_cmd_rewr_parse_add_del(dcb, dev, argc, argv, &tab);
 192        if (ret != 0)
 193                return ret;
 194
 195        ret = dcb_app_add_del(dcb, dev, DCB_CMD_IEEE_DEL, &tab, NULL);
 196        dcb_app_table_fini(&tab);
 197        return ret;
 198}
 199
 200static int dcb_cmd_rewr_replace(struct dcb *dcb, const char *dev, int argc,
 201                                char **argv)
 202{
 203        struct dcb_app_table orig = { .attr = DCB_ATTR_DCB_REWR_TABLE };
 204        struct dcb_app_table tab = { .attr = DCB_ATTR_DCB_REWR_TABLE };
 205        struct dcb_app_table new = { .attr = DCB_ATTR_DCB_REWR_TABLE };
 206        int ret;
 207
 208        ret = dcb_app_get(dcb, dev, &orig);
 209        if (ret != 0)
 210                return ret;
 211
 212        ret = dcb_cmd_rewr_parse_add_del(dcb, dev, argc, argv, &tab);
 213        if (ret != 0)
 214                goto out;
 215
 216        /* Attempts to add an existing entry would be rejected, so drop
 217         * these entries from tab.
 218         */
 219        ret = dcb_app_table_copy(&new, &tab);
 220        if (ret != 0)
 221                goto out;
 222        dcb_app_table_remove_existing(&new, &orig);
 223
 224        ret = dcb_app_add_del(dcb, dev, DCB_CMD_IEEE_SET, &new, NULL);
 225        if (ret != 0) {
 226                fprintf(stderr, "Could not add new rewrite entries\n");
 227                goto out;
 228        }
 229
 230        /* Remove the obsolete entries. */
 231        dcb_app_table_remove_replaced(&orig, &tab, dcb_rewr_prio_eq);
 232        ret = dcb_app_add_del(dcb, dev, DCB_CMD_IEEE_DEL, &orig, NULL);
 233        if (ret != 0) {
 234                fprintf(stderr, "Could not remove replaced rewrite entries\n");
 235                goto out;
 236        }
 237
 238out:
 239        dcb_app_table_fini(&new);
 240        dcb_app_table_fini(&tab);
 241        dcb_app_table_fini(&orig);
 242        return 0;
 243}
 244
 245static int dcb_cmd_rewr_show(struct dcb *dcb, const char *dev, int argc,
 246                             char **argv)
 247{
 248        struct dcb_app_table tab = { .attr = DCB_ATTR_DCB_REWR_TABLE };
 249        int ret;
 250
 251        ret = dcb_app_get(dcb, dev, &tab);
 252        if (ret != 0)
 253                return ret;
 254
 255        dcb_app_table_sort(&tab);
 256
 257        open_json_object(NULL);
 258
 259        if (!argc) {
 260                dcb_rewr_print(dcb, &tab);
 261                goto out;
 262        }
 263
 264        do {
 265                if (strcmp(*argv, "help") == 0) {
 266                        dcb_rewr_help_show_flush();
 267                        goto out;
 268                } else if (strcmp(*argv, "prio-pcp") == 0) {
 269                        dcb_rewr_print_prio_pcp(dcb, &tab);
 270                } else if (strcmp(*argv, "prio-dscp") == 0) {
 271                        dcb_rewr_print_prio_dscp(dcb, &tab);
 272                } else {
 273                        fprintf(stderr, "What is \"%s\"?\n", *argv);
 274                        dcb_rewr_help_show_flush();
 275                        ret = -EINVAL;
 276                        goto out;
 277                }
 278
 279                NEXT_ARG_FWD();
 280        } while (argc > 0);
 281
 282out:
 283        close_json_object();
 284        dcb_app_table_fini(&tab);
 285        return ret;
 286}
 287
 288static int dcb_cmd_rewr_flush(struct dcb *dcb, const char *dev, int argc,
 289                              char **argv)
 290{
 291        struct dcb_app_table tab = { .attr = DCB_ATTR_DCB_REWR_TABLE };
 292        int ret;
 293
 294        ret = dcb_app_get(dcb, dev, &tab);
 295        if (ret != 0)
 296                return ret;
 297
 298        if (!argc) {
 299                ret = dcb_app_add_del(dcb, dev, DCB_CMD_IEEE_DEL, &tab,
 300                                      NULL);
 301                goto out;
 302        }
 303
 304        do {
 305                if (strcmp(*argv, "help") == 0) {
 306                        dcb_rewr_help_show_flush();
 307                        goto out;
 308                } else if (strcmp(*argv, "prio-pcp") == 0) {
 309                        ret = dcb_app_add_del(dcb, dev, DCB_CMD_IEEE_DEL, &tab,
 310                                              &dcb_app_is_pcp);
 311                        if (ret != 0)
 312                                goto out;
 313                } else if (strcmp(*argv, "prio-dscp") == 0) {
 314                        ret = dcb_app_add_del(dcb, dev, DCB_CMD_IEEE_DEL, &tab,
 315                                              &dcb_app_is_dscp);
 316                        if (ret != 0)
 317                                goto out;
 318                } else {
 319                        fprintf(stderr, "What is \"%s\"?\n", *argv);
 320                        dcb_rewr_help_show_flush();
 321                        ret = -EINVAL;
 322                        goto out;
 323                }
 324
 325                NEXT_ARG_FWD();
 326        } while (argc > 0);
 327
 328out:
 329        dcb_app_table_fini(&tab);
 330        return ret;
 331}
 332
 333int dcb_cmd_rewr(struct dcb *dcb, int argc, char **argv)
 334{
 335        if (!argc || strcmp(*argv, "help") == 0) {
 336                dcb_rewr_help();
 337                return 0;
 338        } else if (strcmp(*argv, "show") == 0) {
 339                NEXT_ARG_FWD();
 340                return dcb_cmd_parse_dev(dcb, argc, argv, dcb_cmd_rewr_show,
 341                                         dcb_rewr_help_show_flush);
 342        } else if (strcmp(*argv, "flush") == 0) {
 343                NEXT_ARG_FWD();
 344                return dcb_cmd_parse_dev(dcb, argc, argv, dcb_cmd_rewr_flush,
 345                                         dcb_rewr_help_show_flush);
 346        } else if (strcmp(*argv, "add") == 0) {
 347                NEXT_ARG_FWD();
 348                return dcb_cmd_parse_dev(dcb, argc, argv, dcb_cmd_rewr_add,
 349                                         dcb_rewr_help_add);
 350        } else if (strcmp(*argv, "del") == 0) {
 351                NEXT_ARG_FWD();
 352                return dcb_cmd_parse_dev(dcb, argc, argv, dcb_cmd_rewr_del,
 353                                         dcb_rewr_help_add);
 354        } else if (strcmp(*argv, "replace") == 0) {
 355                NEXT_ARG_FWD();
 356                return dcb_cmd_parse_dev(dcb, argc, argv, dcb_cmd_rewr_replace,
 357                                         dcb_rewr_help_add);
 358        } else {
 359                fprintf(stderr, "What is \"%s\"?\n", *argv);
 360                dcb_rewr_help();
 361                return -EINVAL;
 362        }
 363}
 364