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 (at) 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"); 28 fprintf(stderr, " [queues count1@offset1 count2@offset2 ...] "); 29 fprintf(stderr, "[hw 1|0]\n"); 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; 61 } else if (strcmp(*argv, "queues") == 0) { 62 char *tmp, *tok; 63 64 while (idx < TC_QOPT_MAX_QUEUE && NEXT_ARG_OK()) { 65 NEXT_ARG(); 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); 74 PREV_ARG(); 75 break; 76 } 77 tok = strtok(NULL, "@"); 78 if (get_u16(&opt.offset[idx], tok, 10)) { 79 free(tmp); 80 PREV_ARG(); 81 break; 82 } 83 free(tmp); 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 107 static int mqprio_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt) 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++) 119 fprintf(f, "%u ", qopt->prio_tc_map[i]); 120 fprintf(f, "\n queues:"); 121 for (i = 0; i < qopt->num_tc; i++) 122 fprintf(f, "(%u:%u) ", qopt->offset[i], 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 }; 132