19932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy/* 29932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy * f_flow.c Flow filter 39932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy * 49932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy * This program is free software; you can redistribute it and/or 59932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy * modify it under the terms of the GNU General Public License 69932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy * as published by the Free Software Foundation; either version 79932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy * 2 of the License, or (at your option) any later version. 89932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy * 99932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy * Authors: Patrick McHardy <kaber@trash.net> 109932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy */ 119932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy#include <stdio.h> 129932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy#include <stdlib.h> 139932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy#include <unistd.h> 149932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy#include <string.h> 159932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy#include <errno.h> 169932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy 179932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy#include "utils.h" 189932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy#include "tc_util.h" 199932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy#include "m_ematch.h" 209932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy 219932abb498ca5280027ff57c92a4e948eac41652Patrick McHardystatic void explain(void) 229932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy{ 239932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy fprintf(stderr, 249932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy"Usage: ... flow ...\n" 259932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy"\n" 269932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy" [mapping mode]: map key KEY [ OPS ] ...\n" 2787953940f9a021333c2e753309526121523df56ePatrick McHardy" [hashing mode]: hash keys KEY-LIST ... [ perturb SECS ]\n" 289932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy"\n" 299932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy" [ divisor NUM ] [ baseclass ID ] [ match EMATCH_TREE ]\n" 309932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy" [ police POLICE_SPEC ] [ action ACTION_SPEC ]\n" 319932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy"\n" 329932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy"KEY-LIST := [ KEY-LIST , ] KEY\n" 339932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy"KEY := [ src | dst | proto | proto-src | proto-dst | iif | priority | \n" 349932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy" mark | nfct | nfct-src | nfct-dst | nfct-proto-src | \n" 3566862d3cc704973a3fde309e05912328480745bdPatrick McHardy" nfct-proto-dst | rt-classid | sk-uid | sk-gid |\n" 367162c921488de9093c522b858a1ab488b8f50c96Changli Gao" vlan-tag | rxhash ]\n" 379932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy"OPS := [ or NUM | and NUM | xor NUM | rshift NUM | addend NUM ]\n" 389932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy"ID := X:Y\n" 399932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy ); 409932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy} 419932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy 429932abb498ca5280027ff57c92a4e948eac41652Patrick McHardystatic const char *flow_keys[FLOW_KEY_MAX+1] = { 439932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy [FLOW_KEY_SRC] = "src", 449932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy [FLOW_KEY_DST] = "dst", 459932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy [FLOW_KEY_PROTO] = "proto", 469932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy [FLOW_KEY_PROTO_SRC] = "proto-src", 479932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy [FLOW_KEY_PROTO_DST] = "proto-dst", 489932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy [FLOW_KEY_IIF] = "iif", 499932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy [FLOW_KEY_PRIORITY] = "priority", 509932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy [FLOW_KEY_MARK] = "mark", 519932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy [FLOW_KEY_NFCT] = "nfct", 529932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy [FLOW_KEY_NFCT_SRC] = "nfct-src", 539932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy [FLOW_KEY_NFCT_DST] = "nfct-dst", 549932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy [FLOW_KEY_NFCT_PROTO_SRC] = "nfct-proto-src", 559932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy [FLOW_KEY_NFCT_PROTO_DST] = "nfct-proto-dst", 569932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy [FLOW_KEY_RTCLASSID] = "rt-classid", 579932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy [FLOW_KEY_SKUID] = "sk-uid", 589932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy [FLOW_KEY_SKGID] = "sk-gid", 5966862d3cc704973a3fde309e05912328480745bdPatrick McHardy [FLOW_KEY_VLAN_TAG] = "vlan-tag", 607162c921488de9093c522b858a1ab488b8f50c96Changli Gao [FLOW_KEY_RXHASH] = "rxhash", 619932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy}; 629932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy 639932abb498ca5280027ff57c92a4e948eac41652Patrick McHardystatic int flow_parse_keys(__u32 *keys, __u32 *nkeys, char *argv) 649932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy{ 659932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy char *s, *sep; 669932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy unsigned int i; 679932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy 689932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy *keys = 0; 699932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy *nkeys = 0; 709932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy s = argv; 719932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy while (s != NULL) { 729932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy sep = strchr(s, ','); 739932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy if (sep) 749932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy *sep = '\0'; 759932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy 769932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy for (i = 0; i <= FLOW_KEY_MAX; i++) { 779932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy if (matches(s, flow_keys[i]) == 0) { 789932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy *keys |= 1 << i; 799932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy (*nkeys)++; 809932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy break; 819932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy } 829932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy } 839932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy if (i > FLOW_KEY_MAX) { 849932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy fprintf(stderr, "Unknown flow key \"%s\"\n", s); 859932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy return -1; 869932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy } 879932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy s = sep ? sep + 1 : NULL; 889932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy } 899932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy return 0; 909932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy} 919932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy 929932abb498ca5280027ff57c92a4e948eac41652Patrick McHardystatic void transfer_bitop(__u32 *mask, __u32 *xor, __u32 m, __u32 x) 939932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy{ 949932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy *xor = x ^ (*xor & m); 959932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy *mask &= m; 969932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy} 979932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy 989932abb498ca5280027ff57c92a4e948eac41652Patrick McHardystatic int get_addend(__u32 *addend, char *argv, __u32 keys) 999932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy{ 1009932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy inet_prefix addr; 1019932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy int sign = 0; 1029932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy __u32 tmp; 1039932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy 1049932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy if (*argv == '-') { 1059932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy sign = 1; 1069932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy argv++; 1079932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy } 1089932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy 1099932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy if (get_u32(&tmp, argv, 0) == 0) 1109932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy goto out; 1119932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy 1129932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy if (keys & (FLOW_KEY_SRC | FLOW_KEY_DST | 1139932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy FLOW_KEY_NFCT_SRC | FLOW_KEY_NFCT_DST) && 1149932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy get_addr(&addr, argv, AF_UNSPEC) == 0) { 1159932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy switch (addr.family) { 1169932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy case AF_INET: 1179932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy tmp = ntohl(addr.data[0]); 1189932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy goto out; 1199932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy case AF_INET6: 1209932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy tmp = ntohl(addr.data[3]); 1219932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy goto out; 1229932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy } 1239932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy } 1249932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy 1259932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy return -1; 1269932abb498ca5280027ff57c92a4e948eac41652Patrick McHardyout: 1279932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy if (sign) 1289932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy tmp = -tmp; 1299932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy *addend = tmp; 1309932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy return 0; 1319932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy} 1329932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy 1339932abb498ca5280027ff57c92a4e948eac41652Patrick McHardystatic int flow_parse_opt(struct filter_util *fu, char *handle, 1349932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy int argc, char **argv, struct nlmsghdr *n) 1359932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy{ 1369932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy struct tc_police tp; 1379932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy struct tcmsg *t = NLMSG_DATA(n); 1389932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy struct rtattr *tail; 1399932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy __u32 mask = ~0U, xor = 0; 1409932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy __u32 keys = 0, nkeys = 0; 1419932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy __u32 mode = FLOW_MODE_MAP; 1429932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy __u32 tmp; 1439932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy 1449932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy memset(&tp, 0, sizeof(tp)); 1459932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy 1469932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy if (handle) { 1479932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy if (get_u32(&t->tcm_handle, handle, 0)) { 1489932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy fprintf(stderr, "Illegal \"handle\"\n"); 1499932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy return -1; 1509932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy } 1519932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy } 1529932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy 1539932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy tail = NLMSG_TAIL(n); 1549932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy addattr_l(n, 4096, TCA_OPTIONS, NULL, 0); 1559932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy 1569932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy while (argc > 0) { 1579932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy if (matches(*argv, "map") == 0) { 1589932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy mode = FLOW_MODE_MAP; 1599932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy } else if (matches(*argv, "hash") == 0) { 1609932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy mode = FLOW_MODE_HASH; 1619932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy } else if (matches(*argv, "keys") == 0) { 1629932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy NEXT_ARG(); 1639932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy if (flow_parse_keys(&keys, &nkeys, *argv)) 1649932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy return -1; 1659932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy addattr32(n, 4096, TCA_FLOW_KEYS, keys); 1669932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy } else if (matches(*argv, "and") == 0) { 1679932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy NEXT_ARG(); 1689932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy if (get_u32(&tmp, *argv, 0)) { 1699932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy fprintf(stderr, "Illegal \"mask\"\n"); 1709932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy return -1; 1719932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy } 1729932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy transfer_bitop(&mask, &xor, tmp, 0); 1739932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy } else if (matches(*argv, "or") == 0) { 1749932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy NEXT_ARG(); 1759932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy if (get_u32(&tmp, *argv, 0)) { 1769932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy fprintf(stderr, "Illegal \"or\"\n"); 1779932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy return -1; 1789932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy } 1799932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy transfer_bitop(&mask, &xor, ~tmp, tmp); 1809932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy } else if (matches(*argv, "xor") == 0) { 1819932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy NEXT_ARG(); 1829932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy if (get_u32(&tmp, *argv, 0)) { 1839932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy fprintf(stderr, "Illegal \"xor\"\n"); 1849932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy return -1; 1859932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy } 1869932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy transfer_bitop(&mask, &xor, ~0, tmp); 1879932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy } else if (matches(*argv, "rshift") == 0) { 1889932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy NEXT_ARG(); 1899932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy if (get_u32(&tmp, *argv, 0)) { 1909932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy fprintf(stderr, "Illegal \"rshift\"\n"); 1919932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy return -1; 1929932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy } 1939932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy addattr32(n, 4096, TCA_FLOW_RSHIFT, tmp); 1949932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy } else if (matches(*argv, "addend") == 0) { 1959932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy NEXT_ARG(); 1969932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy if (get_addend(&tmp, *argv, keys)) { 1979932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy fprintf(stderr, "Illegal \"addend\"\n"); 1989932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy return -1; 1999932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy } 2009932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy addattr32(n, 4096, TCA_FLOW_ADDEND, tmp); 2019932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy } else if (matches(*argv, "divisor") == 0) { 2029932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy NEXT_ARG(); 2039932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy if (get_u32(&tmp, *argv, 0)) { 2049932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy fprintf(stderr, "Illegal \"divisor\"\n"); 2059932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy return -1; 2069932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy } 2079932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy addattr32(n, 4096, TCA_FLOW_DIVISOR, tmp); 2089932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy } else if (matches(*argv, "baseclass") == 0) { 2099932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy NEXT_ARG(); 2109932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy if (get_tc_classid(&tmp, *argv) || TC_H_MIN(tmp) == 0) { 2119932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy fprintf(stderr, "Illegal \"baseclass\"\n"); 2129932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy return -1; 2139932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy } 2149932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy addattr32(n, 4096, TCA_FLOW_BASECLASS, tmp); 21587953940f9a021333c2e753309526121523df56ePatrick McHardy } else if (matches(*argv, "perturb") == 0) { 21687953940f9a021333c2e753309526121523df56ePatrick McHardy NEXT_ARG(); 21787953940f9a021333c2e753309526121523df56ePatrick McHardy if (get_u32(&tmp, *argv, 0)) { 21887953940f9a021333c2e753309526121523df56ePatrick McHardy fprintf(stderr, "Illegal \"perturb\"\n"); 21987953940f9a021333c2e753309526121523df56ePatrick McHardy return -1; 22087953940f9a021333c2e753309526121523df56ePatrick McHardy } 22187953940f9a021333c2e753309526121523df56ePatrick McHardy addattr32(n, 4096, TCA_FLOW_PERTURB, tmp); 2229932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy } else if (matches(*argv, "police") == 0) { 2239932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy NEXT_ARG(); 2249932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy if (parse_police(&argc, &argv, TCA_FLOW_POLICE, n)) { 2259932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy fprintf(stderr, "Illegal \"police\"\n"); 2269932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy return -1; 2279932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy } 2289932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy continue; 2299932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy } else if (matches(*argv, "action") == 0) { 2309932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy NEXT_ARG(); 2319932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy if (parse_action(&argc, &argv, TCA_FLOW_ACT, n)) { 2329932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy fprintf(stderr, "Illegal \"action\"\n"); 2339932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy return -1; 2349932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy } 2359932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy continue; 2369932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy } else if (matches(*argv, "match") == 0) { 2379932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy NEXT_ARG(); 2389932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy if (parse_ematch(&argc, &argv, TCA_FLOW_EMATCHES, n)) { 2399932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy fprintf(stderr, "Illegal \"ematch\"\n"); 2409932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy return -1; 2419932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy } 2429932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy continue; 2439932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy } else if (matches(*argv, "help") == 0) { 2449932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy explain(); 2459932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy return -1; 2469932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy } else { 2479932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy fprintf(stderr, "What is \"%s\"?\n", *argv); 2489932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy explain(); 2499932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy return -1; 2509932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy } 2519932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy argv++, argc--; 2529932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy } 2539932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy 2549932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy if (nkeys > 1 && mode != FLOW_MODE_HASH) { 2559932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy fprintf(stderr, "Invalid mode \"map\" for multiple keys\n"); 2569932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy return -1; 2579932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy } 2589932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy addattr32(n, 4096, TCA_FLOW_MODE, mode); 2599932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy 2609932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy if (mask != ~0 || xor != 0) { 2619932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy addattr32(n, 4096, TCA_FLOW_MASK, mask); 2629932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy addattr32(n, 4096, TCA_FLOW_XOR, xor); 2639932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy } 2649932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy 2659932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy tail->rta_len = (void *)NLMSG_TAIL(n) - (void *)tail; 2669932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy return 0; 2679932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy} 2689932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy 2699932abb498ca5280027ff57c92a4e948eac41652Patrick McHardystatic int flow_print_opt(struct filter_util *fu, FILE *f, struct rtattr *opt, 2709932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy __u32 handle) 2719932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy{ 2729932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy struct rtattr *tb[TCA_FLOW_MAX+1]; 2739932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy SPRINT_BUF(b1); 2749932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy unsigned int i; 2759932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy __u32 mask = ~0, val = 0; 2769932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy 2779932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy if (opt == NULL) 2789932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy return -EINVAL; 2799932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy 2809932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy parse_rtattr_nested(tb, TCA_FLOW_MAX, opt); 2819932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy 2829932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy fprintf(f, "handle 0x%x ", handle); 2839932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy 2849932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy if (tb[TCA_FLOW_MODE]) { 285ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger __u32 mode = rta_getattr_u32(tb[TCA_FLOW_MODE]); 2869932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy 2879932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy switch (mode) { 2889932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy case FLOW_MODE_MAP: 2899932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy fprintf(f, "map "); 2909932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy break; 2919932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy case FLOW_MODE_HASH: 2929932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy fprintf(f, "hash "); 2939932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy break; 2949932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy } 2959932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy } 2969932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy 2979932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy if (tb[TCA_FLOW_KEYS]) { 298ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger __u32 keymask = rta_getattr_u32(tb[TCA_FLOW_KEYS]); 2999932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy char *sep = ""; 3009932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy 3019932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy fprintf(f, "keys "); 3029932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy for (i = 0; i <= FLOW_KEY_MAX; i++) { 3039932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy if (keymask & (1 << i)) { 3049932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy fprintf(f, "%s%s", sep, flow_keys[i]); 3059932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy sep = ","; 3069932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy } 3079932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy } 3089932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy fprintf(f, " "); 3099932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy } 3109932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy 3119932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy if (tb[TCA_FLOW_MASK]) 312ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger mask = rta_getattr_u32(tb[TCA_FLOW_MASK]); 3139932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy if (tb[TCA_FLOW_XOR]) 314ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger val = rta_getattr_u32(tb[TCA_FLOW_XOR]); 3159932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy 3169932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy if (mask != ~0 || val != 0) { 3179932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy __u32 or = (mask & val) ^ val; 3189932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy __u32 xor = mask & val; 3199932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy 3209932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy if (mask != ~0) 3219932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy fprintf(f, "and 0x%.8x ", mask); 3229932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy if (xor != 0) 3239932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy fprintf(f, "xor 0x%.8x ", xor); 3249932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy if (or != 0) 3259932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy fprintf(f, "or 0x%.8x ", or); 3269932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy } 3279932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy 3289932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy if (tb[TCA_FLOW_RSHIFT]) 3299932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy fprintf(f, "rshift %u ", 330ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger rta_getattr_u32(tb[TCA_FLOW_RSHIFT])); 3319932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy if (tb[TCA_FLOW_ADDEND]) 3329932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy fprintf(f, "addend 0x%x ", 333ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger rta_getattr_u32(tb[TCA_FLOW_ADDEND])); 3349932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy 3359932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy if (tb[TCA_FLOW_DIVISOR]) 3369932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy fprintf(f, "divisor %u ", 337ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger rta_getattr_u32(tb[TCA_FLOW_DIVISOR])); 3389932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy if (tb[TCA_FLOW_BASECLASS]) 3399932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy fprintf(f, "baseclass %s ", 340ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger sprint_tc_classid(rta_getattr_u32(tb[TCA_FLOW_BASECLASS]), b1)); 3419932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy 34287953940f9a021333c2e753309526121523df56ePatrick McHardy if (tb[TCA_FLOW_PERTURB]) 34387953940f9a021333c2e753309526121523df56ePatrick McHardy fprintf(f, "perturb %usec ", 344ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger rta_getattr_u32(tb[TCA_FLOW_PERTURB])); 34587953940f9a021333c2e753309526121523df56ePatrick McHardy 3469932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy if (tb[TCA_FLOW_EMATCHES]) 3479932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy print_ematch(f, tb[TCA_FLOW_EMATCHES]); 3489932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy if (tb[TCA_FLOW_POLICE]) 3499932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy tc_print_police(f, tb[TCA_FLOW_POLICE]); 3509932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy if (tb[TCA_FLOW_ACT]) { 3519932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy fprintf(f, "\n"); 3529932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy tc_print_action(f, tb[TCA_FLOW_ACT]); 3539932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy } 3549932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy return 0; 3559932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy} 3569932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy 3579932abb498ca5280027ff57c92a4e948eac41652Patrick McHardystruct filter_util flow_filter_util = { 3589932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy .id = "flow", 3599932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy .parse_fopt = flow_parse_opt, 3609932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy .print_fopt = flow_print_opt, 3619932abb498ca5280027ff57c92a4e948eac41652Patrick McHardy}; 362