Home | History | Annotate | Download | only in tc
      1 /*
      2  * m_ife.c	IFE actions module
      3  *
      4  *		This program is free software; you can distribute 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:  J Hadi Salim (jhs (at) mojatatu.com)
     10  *
     11  */
     12 
     13 #include <stdio.h>
     14 #include <stdlib.h>
     15 #include <unistd.h>
     16 #include <syslog.h>
     17 #include <fcntl.h>
     18 #include <sys/socket.h>
     19 #include <netinet/in.h>
     20 #include <arpa/inet.h>
     21 #include <string.h>
     22 #include <linux/netdevice.h>
     23 
     24 #include "rt_names.h"
     25 #include "utils.h"
     26 #include "tc_util.h"
     27 #include <linux/tc_act/tc_ife.h>
     28 
     29 static void ife_explain(void)
     30 {
     31 	fprintf(stderr,
     32 		"Usage:... ife {decode|encode} [{ALLOW|USE} ATTR] [dst DMAC] [src SMAC] [type TYPE] [CONTROL] [index INDEX]\n");
     33 	fprintf(stderr,
     34 		"\tALLOW := Encode direction. Allows encoding specified metadata\n"
     35 		"\t\t e.g \"allow mark\"\n"
     36 		"\tUSE := Encode direction. Enforce Static encoding of specified metadata\n"
     37 		"\t\t e.g \"use mark 0x12\"\n"
     38 		"\tATTR := mark (32-bit), prio (32-bit), tcindex (16-bit)\n"
     39 		"\tDMAC := 6 byte Destination MAC address to encode\n"
     40 		"\tSMAC := optional 6 byte Source MAC address to encode\n"
     41 		"\tTYPE := optional 16 bit ethertype to encode\n"
     42 		"\tCONTROL := reclassify|pipe|drop|continue|ok\n"
     43 		"\tINDEX := optional IFE table index value used\n");
     44 	fprintf(stderr, "encode is used for sending IFE packets\n");
     45 	fprintf(stderr, "decode is used for receiving IFE packets\n");
     46 }
     47 
     48 static void ife_usage(void)
     49 {
     50 	ife_explain();
     51 	exit(-1);
     52 }
     53 
     54 static int parse_ife(struct action_util *a, int *argc_p, char ***argv_p,
     55 		     int tca_id, struct nlmsghdr *n)
     56 {
     57 	int argc = *argc_p;
     58 	char **argv = *argv_p;
     59 	int ok = 0;
     60 	struct tc_ife p = { 0 };
     61 	struct rtattr *tail;
     62 	struct rtattr *tail2;
     63 	char dbuf[ETH_ALEN];
     64 	char sbuf[ETH_ALEN];
     65 	__u16 ife_type = 0;
     66 	int user_type = 0;
     67 	__u32 ife_prio = 0;
     68 	__u32 ife_prio_v = 0;
     69 	__u32 ife_mark = 0;
     70 	__u32 ife_mark_v = 0;
     71 	__u16 ife_tcindex = 0;
     72 	__u16 ife_tcindex_v = 0;
     73 	char *daddr = NULL;
     74 	char *saddr = NULL;
     75 
     76 	if (argc <= 0)
     77 		return -1;
     78 
     79 	while (argc > 0) {
     80 		if (matches(*argv, "ife") == 0) {
     81 			NEXT_ARG();
     82 			continue;
     83 		} else if (matches(*argv, "decode") == 0) {
     84 			p.flags = IFE_DECODE; /* readability aid */
     85 			ok++;
     86 		} else if (matches(*argv, "encode") == 0) {
     87 			p.flags = IFE_ENCODE;
     88 			ok++;
     89 		} else if (matches(*argv, "allow") == 0) {
     90 			NEXT_ARG();
     91 			if (matches(*argv, "mark") == 0) {
     92 				ife_mark = IFE_META_SKBMARK;
     93 			} else if (matches(*argv, "prio") == 0) {
     94 				ife_prio = IFE_META_PRIO;
     95 			} else if (matches(*argv, "tcindex") == 0) {
     96 				ife_tcindex = IFE_META_TCINDEX;
     97 			} else {
     98 				fprintf(stderr, "Illegal meta define <%s>\n",
     99 					*argv);
    100 				return -1;
    101 			}
    102 		} else if (matches(*argv, "use") == 0) {
    103 			NEXT_ARG();
    104 			if (matches(*argv, "mark") == 0) {
    105 				NEXT_ARG();
    106 				if (get_u32(&ife_mark_v, *argv, 0))
    107 					invarg("ife mark val is invalid",
    108 					       *argv);
    109 			} else if (matches(*argv, "prio") == 0) {
    110 				NEXT_ARG();
    111 				if (get_u32(&ife_prio_v, *argv, 0))
    112 					invarg("ife prio val is invalid",
    113 					       *argv);
    114 			} else if (matches(*argv, "tcindex") == 0) {
    115 				NEXT_ARG();
    116 				if (get_u16(&ife_tcindex_v, *argv, 0))
    117 					invarg("ife tcindex val is invalid",
    118 					       *argv);
    119 			} else {
    120 				fprintf(stderr, "Illegal meta use type <%s>\n",
    121 					*argv);
    122 				return -1;
    123 			}
    124 		} else if (matches(*argv, "type") == 0) {
    125 			NEXT_ARG();
    126 			if (get_u16(&ife_type, *argv, 0))
    127 				invarg("ife type is invalid", *argv);
    128 			fprintf(stderr, "IFE type 0x%04X\n", ife_type);
    129 			user_type = 1;
    130 		} else if (matches(*argv, "dst") == 0) {
    131 			NEXT_ARG();
    132 			daddr = *argv;
    133 			if (sscanf(daddr, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
    134 				   dbuf, dbuf + 1, dbuf + 2,
    135 				   dbuf + 3, dbuf + 4, dbuf + 5) != 6) {
    136 				fprintf(stderr, "Invalid mac address %s\n",
    137 					daddr);
    138 			}
    139 			fprintf(stderr, "dst MAC address <%s>\n", daddr);
    140 
    141 		} else if (matches(*argv, "src") == 0) {
    142 			NEXT_ARG();
    143 			saddr = *argv;
    144 			if (sscanf(saddr, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
    145 				   sbuf, sbuf + 1, sbuf + 2,
    146 				   sbuf + 3, sbuf + 4, sbuf + 5) != 6) {
    147 				fprintf(stderr, "Invalid mac address %s\n",
    148 					saddr);
    149 			}
    150 			fprintf(stderr, "src MAC address <%s>\n", saddr);
    151 		} else if (matches(*argv, "help") == 0) {
    152 			ife_usage();
    153 		} else {
    154 			break;
    155 		}
    156 
    157 		argc--;
    158 		argv++;
    159 	}
    160 
    161 	parse_action_control_dflt(&argc, &argv, &p.action, false, TC_ACT_PIPE);
    162 
    163 	if (argc) {
    164 		if (matches(*argv, "index") == 0) {
    165 			NEXT_ARG();
    166 			if (get_u32(&p.index, *argv, 0)) {
    167 				fprintf(stderr, "ife: Illegal \"index\"\n");
    168 				return -1;
    169 			}
    170 			ok++;
    171 			argc--;
    172 			argv++;
    173 		}
    174 	}
    175 
    176 	if (!ok) {
    177 		fprintf(stderr, "IFE requires decode/encode specified\n");
    178 		ife_usage();
    179 	}
    180 
    181 	tail = NLMSG_TAIL(n);
    182 	addattr_l(n, MAX_MSG, tca_id, NULL, 0);
    183 	addattr_l(n, MAX_MSG, TCA_IFE_PARMS, &p, sizeof(p));
    184 
    185 	if (!(p.flags & IFE_ENCODE))
    186 		goto skip_encode;
    187 
    188 	if (daddr)
    189 		addattr_l(n, MAX_MSG, TCA_IFE_DMAC, dbuf, ETH_ALEN);
    190 	if (user_type)
    191 		addattr_l(n, MAX_MSG, TCA_IFE_TYPE, &ife_type, 2);
    192 	else
    193 		fprintf(stderr, "IFE type 0x%04X\n", ETH_P_IFE);
    194 	if (saddr)
    195 		addattr_l(n, MAX_MSG, TCA_IFE_SMAC, sbuf, ETH_ALEN);
    196 
    197 	tail2 = NLMSG_TAIL(n);
    198 	addattr_l(n, MAX_MSG, TCA_IFE_METALST, NULL, 0);
    199 	if (ife_mark || ife_mark_v) {
    200 		if (ife_mark_v)
    201 			addattr_l(n, MAX_MSG, IFE_META_SKBMARK, &ife_mark_v, 4);
    202 		else
    203 			addattr_l(n, MAX_MSG, IFE_META_SKBMARK, NULL, 0);
    204 	}
    205 	if (ife_prio || ife_prio_v) {
    206 		if (ife_prio_v)
    207 			addattr_l(n, MAX_MSG, IFE_META_PRIO, &ife_prio_v, 4);
    208 		else
    209 			addattr_l(n, MAX_MSG, IFE_META_PRIO, NULL, 0);
    210 	}
    211 	if (ife_tcindex || ife_tcindex_v) {
    212 		if (ife_tcindex_v)
    213 			addattr_l(n, MAX_MSG, IFE_META_TCINDEX, &ife_tcindex_v,
    214 				  2);
    215 		else
    216 			addattr_l(n, MAX_MSG, IFE_META_TCINDEX, NULL, 0);
    217 	}
    218 
    219 	tail2->rta_len = (void *)NLMSG_TAIL(n) - (void *)tail2;
    220 
    221 skip_encode:
    222 	tail->rta_len = (void *)NLMSG_TAIL(n) - (void *)tail;
    223 
    224 	*argc_p = argc;
    225 	*argv_p = argv;
    226 	return 0;
    227 }
    228 
    229 static int print_ife(struct action_util *au, FILE *f, struct rtattr *arg)
    230 {
    231 	struct tc_ife *p = NULL;
    232 	struct rtattr *tb[TCA_IFE_MAX + 1];
    233 	__u16 ife_type = 0;
    234 	__u32 mmark = 0;
    235 	__u16 mtcindex = 0;
    236 	__u32 mprio = 0;
    237 	int has_optional = 0;
    238 	SPRINT_BUF(b2);
    239 
    240 	if (arg == NULL)
    241 		return -1;
    242 
    243 	parse_rtattr_nested(tb, TCA_IFE_MAX, arg);
    244 
    245 	if (tb[TCA_IFE_PARMS] == NULL) {
    246 		fprintf(f, "[NULL ife parameters]");
    247 		return -1;
    248 	}
    249 	p = RTA_DATA(tb[TCA_IFE_PARMS]);
    250 
    251 	fprintf(f, "ife %s ", p->flags & IFE_ENCODE ? "encode" : "decode");
    252 	print_action_control(f, "action ", p->action, " ");
    253 
    254 	if (tb[TCA_IFE_TYPE]) {
    255 		ife_type = rta_getattr_u16(tb[TCA_IFE_TYPE]);
    256 		has_optional = 1;
    257 		fprintf(f, "type 0x%X ", ife_type);
    258 	}
    259 
    260 	if (has_optional)
    261 		fprintf(f, "\n\t ");
    262 
    263 	if (tb[TCA_IFE_METALST]) {
    264 		struct rtattr *metalist[IFE_META_MAX + 1];
    265 		int len = 0;
    266 
    267 		parse_rtattr_nested(metalist, IFE_META_MAX,
    268 				    tb[TCA_IFE_METALST]);
    269 
    270 		if (metalist[IFE_META_SKBMARK]) {
    271 			len = RTA_PAYLOAD(metalist[IFE_META_SKBMARK]);
    272 			if (len) {
    273 				mmark = rta_getattr_u32(metalist[IFE_META_SKBMARK]);
    274 				fprintf(f, "use mark %u ", mmark);
    275 			} else
    276 				fprintf(f, "allow mark ");
    277 		}
    278 
    279 		if (metalist[IFE_META_TCINDEX]) {
    280 			len = RTA_PAYLOAD(metalist[IFE_META_TCINDEX]);
    281 			if (len) {
    282 				mtcindex =
    283 					rta_getattr_u16(metalist[IFE_META_TCINDEX]);
    284 				fprintf(f, "use tcindex %d ", mtcindex);
    285 			} else
    286 				fprintf(f, "allow tcindex ");
    287 		}
    288 
    289 		if (metalist[IFE_META_PRIO]) {
    290 			len = RTA_PAYLOAD(metalist[IFE_META_PRIO]);
    291 			if (len) {
    292 				mprio = rta_getattr_u32(metalist[IFE_META_PRIO]);
    293 				fprintf(f, "use prio %u ", mprio);
    294 			} else
    295 				fprintf(f, "allow prio ");
    296 		}
    297 
    298 	}
    299 
    300 	if (tb[TCA_IFE_DMAC]) {
    301 		has_optional = 1;
    302 		fprintf(f, "dst %s ",
    303 			ll_addr_n2a(RTA_DATA(tb[TCA_IFE_DMAC]),
    304 				    RTA_PAYLOAD(tb[TCA_IFE_DMAC]), 0, b2,
    305 				    sizeof(b2)));
    306 
    307 	}
    308 
    309 	if (tb[TCA_IFE_SMAC]) {
    310 		has_optional = 1;
    311 		fprintf(f, "src %s ",
    312 			ll_addr_n2a(RTA_DATA(tb[TCA_IFE_SMAC]),
    313 				    RTA_PAYLOAD(tb[TCA_IFE_SMAC]), 0, b2,
    314 				    sizeof(b2)));
    315 	}
    316 
    317 	fprintf(f, "\n\t index %u ref %d bind %d", p->index, p->refcnt,
    318 		p->bindcnt);
    319 	if (show_stats) {
    320 		if (tb[TCA_IFE_TM]) {
    321 			struct tcf_t *tm = RTA_DATA(tb[TCA_IFE_TM]);
    322 
    323 			print_tm(f, tm);
    324 		}
    325 	}
    326 
    327 	fprintf(f, "\n");
    328 
    329 	return 0;
    330 }
    331 
    332 struct action_util ife_action_util = {
    333 	.id = "ife",
    334 	.parse_aopt = parse_ife,
    335 	.print_aopt = print_ife,
    336 };
    337