John Fastabend | 9149530 | 2011-04-12 08:57:27 -0700 | [diff] [blame] | 1 | /* |
| 2 | * q_mqprio.c MQ prio qdisc |
| 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 | * Author: John Fastabend, <john.r.fastabend@intel.com> |
| 10 | */ |
| 11 | |
| 12 | #include <stdio.h> |
| 13 | #include <stdlib.h> |
| 14 | #include <unistd.h> |
| 15 | #include <syslog.h> |
| 16 | #include <fcntl.h> |
| 17 | #include <sys/socket.h> |
| 18 | #include <netinet/in.h> |
| 19 | #include <arpa/inet.h> |
| 20 | #include <string.h> |
| 21 | |
| 22 | #include "utils.h" |
| 23 | #include "tc_util.h" |
| 24 | |
| 25 | static void explain(void) |
| 26 | { |
| 27 | fprintf(stderr, "Usage: ... mqprio [num_tc NUMBER] [map P0 P1 ...]\n"); |
John Fastabend | 892eba3 | 2011-04-26 12:44:42 -0700 | [diff] [blame] | 28 | fprintf(stderr, " [queues count1@offset1 count2@offset2 ...] "); |
| 29 | fprintf(stderr, "[hw 1|0]\n"); |
John Fastabend | 9149530 | 2011-04-12 08:57:27 -0700 | [diff] [blame] | 30 | } |
| 31 | |
| 32 | static int mqprio_parse_opt(struct qdisc_util *qu, int argc, |
| 33 | char **argv, struct nlmsghdr *n) |
| 34 | { |
| 35 | int idx; |
| 36 | struct tc_mqprio_qopt opt = { |
| 37 | 8, |
| 38 | {0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 1, 1, 3, 3, 3, 3}, |
| 39 | 1, |
| 40 | }; |
| 41 | |
| 42 | while (argc > 0) { |
| 43 | idx = 0; |
| 44 | if (strcmp(*argv, "num_tc") == 0) { |
| 45 | NEXT_ARG(); |
| 46 | if (get_u8(&opt.num_tc, *argv, 10)) { |
| 47 | fprintf(stderr, "Illegal \"num_tc\"\n"); |
| 48 | return -1; |
| 49 | } |
| 50 | } else if (strcmp(*argv, "map") == 0) { |
| 51 | while (idx < TC_QOPT_MAX_QUEUE && NEXT_ARG_OK()) { |
| 52 | NEXT_ARG(); |
| 53 | if (get_u8(&opt.prio_tc_map[idx], *argv, 10)) { |
| 54 | PREV_ARG(); |
| 55 | break; |
| 56 | } |
| 57 | idx++; |
| 58 | } |
| 59 | for ( ; idx < TC_QOPT_MAX_QUEUE; idx++) |
| 60 | opt.prio_tc_map[idx] = 0; |
John Fastabend | 892eba3 | 2011-04-26 12:44:42 -0700 | [diff] [blame] | 61 | } else if (strcmp(*argv, "queues") == 0) { |
| 62 | char *tmp, *tok; |
| 63 | |
John Fastabend | 9149530 | 2011-04-12 08:57:27 -0700 | [diff] [blame] | 64 | while (idx < TC_QOPT_MAX_QUEUE && NEXT_ARG_OK()) { |
| 65 | NEXT_ARG(); |
John Fastabend | 892eba3 | 2011-04-26 12:44:42 -0700 | [diff] [blame] | 66 | |
| 67 | tmp = strdup(*argv); |
| 68 | if (!tmp) |
| 69 | break; |
| 70 | |
| 71 | tok = strtok(tmp, "@"); |
| 72 | if (get_u16(&opt.count[idx], tok, 10)) { |
| 73 | free(tmp); |
John Fastabend | 9149530 | 2011-04-12 08:57:27 -0700 | [diff] [blame] | 74 | PREV_ARG(); |
| 75 | break; |
| 76 | } |
John Fastabend | 892eba3 | 2011-04-26 12:44:42 -0700 | [diff] [blame] | 77 | tok = strtok(NULL, "@"); |
| 78 | if (get_u16(&opt.offset[idx], tok, 10)) { |
| 79 | free(tmp); |
John Fastabend | 9149530 | 2011-04-12 08:57:27 -0700 | [diff] [blame] | 80 | PREV_ARG(); |
| 81 | break; |
| 82 | } |
John Fastabend | 892eba3 | 2011-04-26 12:44:42 -0700 | [diff] [blame] | 83 | free(tmp); |
John Fastabend | 9149530 | 2011-04-12 08:57:27 -0700 | [diff] [blame] | 84 | idx++; |
| 85 | } |
| 86 | } else if (strcmp(*argv, "hw") == 0) { |
| 87 | NEXT_ARG(); |
| 88 | if (get_u8(&opt.hw, *argv, 10)) { |
| 89 | fprintf(stderr, "Illegal \"hw\"\n"); |
| 90 | return -1; |
| 91 | } |
| 92 | idx++; |
| 93 | } else if (strcmp(*argv, "help") == 0) { |
| 94 | explain(); |
| 95 | return -1; |
| 96 | } else { |
| 97 | fprintf(stderr, "Unknown argument\n"); |
| 98 | return -1; |
| 99 | } |
| 100 | argc--; argv++; |
| 101 | } |
| 102 | |
| 103 | addattr_l(n, 1024, TCA_OPTIONS, &opt, sizeof(opt)); |
| 104 | return 0; |
| 105 | } |
| 106 | |
Stephen Hemminger | d1f28cf | 2013-02-12 11:09:03 -0800 | [diff] [blame] | 107 | static int mqprio_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt) |
John Fastabend | 9149530 | 2011-04-12 08:57:27 -0700 | [diff] [blame] | 108 | { |
| 109 | int i; |
| 110 | struct tc_mqprio_qopt *qopt; |
| 111 | |
| 112 | if (opt == NULL) |
| 113 | return 0; |
| 114 | |
| 115 | qopt = RTA_DATA(opt); |
| 116 | |
| 117 | fprintf(f, " tc %u map ", qopt->num_tc); |
| 118 | for (i = 0; i <= TC_PRIO_MAX; i++) |
Petr Sabata | e2a4536 | 2012-02-15 06:02:33 +0000 | [diff] [blame] | 119 | fprintf(f, "%u ", qopt->prio_tc_map[i]); |
John Fastabend | 9149530 | 2011-04-12 08:57:27 -0700 | [diff] [blame] | 120 | fprintf(f, "\n queues:"); |
| 121 | for (i = 0; i < qopt->num_tc; i++) |
Petr Sabata | e2a4536 | 2012-02-15 06:02:33 +0000 | [diff] [blame] | 122 | fprintf(f, "(%u:%u) ", qopt->offset[i], |
John Fastabend | 9149530 | 2011-04-12 08:57:27 -0700 | [diff] [blame] | 123 | qopt->offset[i] + qopt->count[i] - 1); |
| 124 | return 0; |
| 125 | } |
| 126 | |
| 127 | struct qdisc_util mqprio_qdisc_util = { |
| 128 | .id = "mqprio", |
| 129 | .parse_qopt = mqprio_parse_opt, |
| 130 | .print_qopt = mqprio_print_opt, |
| 131 | }; |