Jamal Hadi Salim | 087f46e | 2013-09-29 07:33:42 -0400 | [diff] [blame] | 1 | /* |
| 2 | * m_simple.c simple action |
| 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@mojatatu.com> |
| 10 | * |
Stephen Hemminger | b2e116d | 2014-12-03 19:28:34 -0800 | [diff] [blame] | 11 | * Pedagogical example. Adds a string that will be printed every time |
Stephen Hemminger | 3d0b743 | 2014-12-20 15:47:17 -0800 | [diff] [blame] | 12 | * the simple instance is hit. |
Jamal Hadi Salim | 087f46e | 2013-09-29 07:33:42 -0400 | [diff] [blame] | 13 | * Use this as a skeleton action and keep modifying it to meet your needs. |
| 14 | * Look at linux/tc_act/tc_defact.h for the different components ids and |
| 15 | * definitions used in this actions |
| 16 | * |
| 17 | * example use, yell "Incoming ICMP!" every time you see an incoming ICMP on |
| 18 | * eth0. Steps are: |
| 19 | * 1) Add an ingress qdisc point to eth0 |
| 20 | * 2) Start a chain on ingress of eth0 that first matches ICMP then invokes |
| 21 | * the simple action to shout. |
| 22 | * 3) display stats and show that no packet has been seen by the action |
| 23 | * 4) Send one ping packet to google (expect to receive a response back) |
| 24 | * 5) grep the logs to see the logged message |
| 25 | * 6) display stats again and observe increment by 1 |
| 26 | * |
| 27 | hadi@noma1:$ tc qdisc add dev eth0 ingress |
| 28 | hadi@noma1:$tc filter add dev eth0 parent ffff: protocol ip prio 5 \ |
Stephen Hemminger | 3d0b743 | 2014-12-20 15:47:17 -0800 | [diff] [blame] | 29 | u32 match ip protocol 1 0xff flowid 1:1 action simple "Incoming ICMP" |
| 30 | |
Jamal Hadi Salim | 087f46e | 2013-09-29 07:33:42 -0400 | [diff] [blame] | 31 | hadi@noma1:$ sudo tc -s filter ls dev eth0 parent ffff: |
Stephen Hemminger | 3d0b743 | 2014-12-20 15:47:17 -0800 | [diff] [blame] | 32 | filter protocol ip pref 5 u32 |
| 33 | filter protocol ip pref 5 u32 fh 800: ht divisor 1 |
| 34 | filter protocol ip pref 5 u32 fh 800::800 order 2048 key ht 800 bkt 0 flowid 1:1 |
Jamal Hadi Salim | 087f46e | 2013-09-29 07:33:42 -0400 | [diff] [blame] | 35 | match 00010000/00ff0000 at 8 |
Stephen Hemminger | 3d0b743 | 2014-12-20 15:47:17 -0800 | [diff] [blame] | 36 | action order 1: Simple <Incoming ICMP> |
| 37 | index 4 ref 1 bind 1 installed 29 sec used 29 sec |
| 38 | Action statistics: |
| 39 | Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0) |
| 40 | backlog 0b 0p requeues 0 |
| 41 | |
| 42 | |
Jamal Hadi Salim | 087f46e | 2013-09-29 07:33:42 -0400 | [diff] [blame] | 43 | hadi@noma1$ ping -c 1 www.google.ca |
| 44 | PING www.google.ca (74.125.225.120) 56(84) bytes of data. |
| 45 | 64 bytes from ord08s08-in-f24.1e100.net (74.125.225.120): icmp_req=1 ttl=53 time=31.3 ms |
| 46 | |
| 47 | --- www.google.ca ping statistics --- |
| 48 | 1 packets transmitted, 1 received, 0% packet loss, time 0ms |
| 49 | rtt min/avg/max/mdev = 31.316/31.316/31.316/0.000 ms |
| 50 | |
| 51 | hadi@noma1$ dmesg | grep simple |
| 52 | [135354.473951] simple: Incoming ICMP_1 |
| 53 | |
| 54 | hadi@noma1$ sudo tc/tc -s filter ls dev eth0 parent ffff: |
Stephen Hemminger | 3d0b743 | 2014-12-20 15:47:17 -0800 | [diff] [blame] | 55 | filter protocol ip pref 5 u32 |
| 56 | filter protocol ip pref 5 u32 fh 800: ht divisor 1 |
| 57 | filter protocol ip pref 5 u32 fh 800::800 order 2048 key ht 800 bkt 0 flowid 1:1 |
Jamal Hadi Salim | 087f46e | 2013-09-29 07:33:42 -0400 | [diff] [blame] | 58 | match 00010000/00ff0000 at 8 |
| 59 | action order 1: Simple <Incoming ICMP> |
| 60 | index 4 ref 1 bind 1 installed 206 sec used 67 sec |
| 61 | Action statistics: |
Stephen Hemminger | 3d0b743 | 2014-12-20 15:47:17 -0800 | [diff] [blame] | 62 | Sent 84 bytes 1 pkt (dropped 0, overlimits 0 requeues 0) |
| 63 | backlog 0b 0p requeues 0 |
Jamal Hadi Salim | 087f46e | 2013-09-29 07:33:42 -0400 | [diff] [blame] | 64 | */ |
| 65 | |
| 66 | #include <stdio.h> |
| 67 | #include <stdlib.h> |
| 68 | #include <unistd.h> |
| 69 | #include <syslog.h> |
| 70 | #include <fcntl.h> |
| 71 | #include <sys/socket.h> |
| 72 | #include <netinet/in.h> |
| 73 | #include <arpa/inet.h> |
| 74 | #include <string.h> |
| 75 | #include "utils.h" |
| 76 | #include "tc_util.h" |
| 77 | #include <linux/tc_act/tc_defact.h> |
| 78 | |
| 79 | #ifndef SIMP_MAX_DATA |
| 80 | #define SIMP_MAX_DATA 32 |
| 81 | #endif |
| 82 | static void explain(void) |
| 83 | { |
Jamal Hadi Salim | fdf1bdd | 2016-05-08 11:02:06 -0400 | [diff] [blame] | 84 | fprintf(stderr, "Usage:... simple [sdata STRING] [CONTROL] [index INDEX]\n"); |
| 85 | fprintf(stderr, "\tSTRING being an arbitrary string\n" |
| 86 | "\tCONTROL := reclassify|pipe|drop|continue|ok\n" |
| 87 | "\tINDEX := optional index value used\n"); |
Jamal Hadi Salim | 087f46e | 2013-09-29 07:33:42 -0400 | [diff] [blame] | 88 | } |
| 89 | |
| 90 | static void usage(void) |
| 91 | { |
| 92 | explain(); |
| 93 | exit(-1); |
| 94 | } |
| 95 | |
| 96 | static int |
| 97 | parse_simple(struct action_util *a, int *argc_p, char ***argv_p, int tca_id, |
| 98 | struct nlmsghdr *n) |
| 99 | { |
| 100 | struct tc_defact sel = {}; |
| 101 | int argc = *argc_p; |
| 102 | char **argv = *argv_p; |
Jamal Hadi Salim | e70b9f1 | 2016-05-24 07:52:48 -0400 | [diff] [blame] | 103 | int ok = 0; |
Jamal Hadi Salim | 087f46e | 2013-09-29 07:33:42 -0400 | [diff] [blame] | 104 | struct rtattr *tail; |
| 105 | char *simpdata = NULL; |
| 106 | |
Jamal Hadi Salim | 087f46e | 2013-09-29 07:33:42 -0400 | [diff] [blame] | 107 | while (argc > 0) { |
| 108 | if (matches(*argv, "simple") == 0) { |
| 109 | NEXT_ARG(); |
Jamal Hadi Salim | fdf1bdd | 2016-05-08 11:02:06 -0400 | [diff] [blame] | 110 | } else if (matches(*argv, "sdata") == 0) { |
| 111 | NEXT_ARG(); |
| 112 | ok += 1; |
Jamal Hadi Salim | 087f46e | 2013-09-29 07:33:42 -0400 | [diff] [blame] | 113 | simpdata = *argv; |
Jamal Hadi Salim | 087f46e | 2013-09-29 07:33:42 -0400 | [diff] [blame] | 114 | argc--; |
| 115 | argv++; |
Jamal Hadi Salim | 087f46e | 2013-09-29 07:33:42 -0400 | [diff] [blame] | 116 | } else if (matches(*argv, "help") == 0) { |
| 117 | usage(); |
| 118 | } else { |
| 119 | break; |
| 120 | } |
Jamal Hadi Salim | fdf1bdd | 2016-05-08 11:02:06 -0400 | [diff] [blame] | 121 | } |
Jamal Hadi Salim | 087f46e | 2013-09-29 07:33:42 -0400 | [diff] [blame] | 122 | |
Phil Sutter | 69f5aff | 2016-07-23 13:28:09 +0200 | [diff] [blame] | 123 | if (argc && !action_a2n(*argv, &sel.action, false)) |
| 124 | NEXT_ARG_FWD(); |
Jamal Hadi Salim | fdf1bdd | 2016-05-08 11:02:06 -0400 | [diff] [blame] | 125 | |
| 126 | if (argc) { |
| 127 | if (matches(*argv, "index") == 0) { |
| 128 | NEXT_ARG(); |
| 129 | if (get_u32(&sel.index, *argv, 10)) { |
Jamal Hadi Salim | e70b9f1 | 2016-05-24 07:52:48 -0400 | [diff] [blame] | 130 | fprintf(stderr, "simple: Illegal \"index\" (%s)\n", |
Jamal Hadi Salim | fdf1bdd | 2016-05-08 11:02:06 -0400 | [diff] [blame] | 131 | *argv); |
| 132 | return -1; |
| 133 | } |
| 134 | ok += 1; |
| 135 | argc--; |
| 136 | argv++; |
| 137 | } |
Jamal Hadi Salim | 087f46e | 2013-09-29 07:33:42 -0400 | [diff] [blame] | 138 | } |
| 139 | |
| 140 | if (!ok) { |
| 141 | explain(); |
| 142 | return -1; |
| 143 | } |
| 144 | |
Jamal Hadi Salim | fdf1bdd | 2016-05-08 11:02:06 -0400 | [diff] [blame] | 145 | if (simpdata && (strlen(simpdata) > (SIMP_MAX_DATA - 1))) { |
Stephen Hemminger | 32a121c | 2016-03-21 11:48:36 -0700 | [diff] [blame] | 146 | fprintf(stderr, "simple: Illegal string len %zu <%s>\n", |
Jamal Hadi Salim | 087f46e | 2013-09-29 07:33:42 -0400 | [diff] [blame] | 147 | strlen(simpdata), simpdata); |
| 148 | return -1; |
| 149 | } |
| 150 | |
| 151 | sel.action = TC_ACT_PIPE; |
| 152 | |
| 153 | tail = NLMSG_TAIL(n); |
| 154 | addattr_l(n, MAX_MSG, tca_id, NULL, 0); |
| 155 | addattr_l(n, MAX_MSG, TCA_DEF_PARMS, &sel, sizeof(sel)); |
Jamal Hadi Salim | fdf1bdd | 2016-05-08 11:02:06 -0400 | [diff] [blame] | 156 | if (simpdata) |
| 157 | addattr_l(n, MAX_MSG, TCA_DEF_DATA, simpdata, SIMP_MAX_DATA); |
Jamal Hadi Salim | 087f46e | 2013-09-29 07:33:42 -0400 | [diff] [blame] | 158 | tail->rta_len = (char *)NLMSG_TAIL(n) - (char *)tail; |
| 159 | |
| 160 | *argc_p = argc; |
| 161 | *argv_p = argv; |
| 162 | return 0; |
| 163 | } |
| 164 | |
Stephen Hemminger | 32a121c | 2016-03-21 11:48:36 -0700 | [diff] [blame] | 165 | static int print_simple(struct action_util *au, FILE *f, struct rtattr *arg) |
Jamal Hadi Salim | 087f46e | 2013-09-29 07:33:42 -0400 | [diff] [blame] | 166 | { |
| 167 | struct tc_defact *sel; |
| 168 | struct rtattr *tb[TCA_DEF_MAX + 1]; |
| 169 | char *simpdata; |
| 170 | |
| 171 | if (arg == NULL) |
| 172 | return -1; |
| 173 | |
| 174 | parse_rtattr_nested(tb, TCA_DEF_MAX, arg); |
| 175 | |
| 176 | if (tb[TCA_DEF_PARMS] == NULL) { |
| 177 | fprintf(f, "[NULL simple parameters]"); |
| 178 | return -1; |
| 179 | } |
| 180 | sel = RTA_DATA(tb[TCA_DEF_PARMS]); |
| 181 | |
| 182 | if (tb[TCA_DEF_DATA] == NULL) { |
| 183 | fprintf(f, "[missing simple string]"); |
| 184 | return -1; |
| 185 | } |
| 186 | |
| 187 | simpdata = RTA_DATA(tb[TCA_DEF_DATA]); |
| 188 | |
| 189 | fprintf(f, "Simple <%s>\n", simpdata); |
| 190 | fprintf(f, "\t index %d ref %d bind %d", sel->index, |
| 191 | sel->refcnt, sel->bindcnt); |
| 192 | |
| 193 | if (show_stats) { |
| 194 | if (tb[TCA_DEF_TM]) { |
| 195 | struct tcf_t *tm = RTA_DATA(tb[TCA_DEF_TM]); |
Stephen Hemminger | 32a121c | 2016-03-21 11:48:36 -0700 | [diff] [blame] | 196 | |
Jamal Hadi Salim | 087f46e | 2013-09-29 07:33:42 -0400 | [diff] [blame] | 197 | print_tm(f, tm); |
Jamal Hadi Salim | 087f46e | 2013-09-29 07:33:42 -0400 | [diff] [blame] | 198 | } |
| 199 | } |
Jamal Hadi Salim | 352f6f9 | 2013-12-22 07:50:09 -0500 | [diff] [blame] | 200 | fprintf(f, "\n"); |
Jamal Hadi Salim | 087f46e | 2013-09-29 07:33:42 -0400 | [diff] [blame] | 201 | |
| 202 | return 0; |
| 203 | } |
| 204 | |
| 205 | struct action_util simple_action_util = { |
| 206 | .id = "simple", |
| 207 | .parse_aopt = parse_simple, |
| 208 | .print_aopt = print_simple, |
| 209 | }; |