]> git.ipfire.org Git - thirdparty/iproute2.git/commitdiff
Add u32 extension to match on ether source/destination
authorStephen Hemminger <stephen.hemminger@vyatta.com>
Wed, 15 Apr 2009 22:39:34 +0000 (15:39 -0700)
committerStephen Hemminger <stephen.hemminger@vyatta.com>
Wed, 15 Apr 2009 22:39:34 +0000 (15:39 -0700)
Use existing u32 mechanism to match based on Ethernet header.
No need for protocol that already exists.

tc/f_u32.c

index e5b8231f53c89ffa44ef1bb740e7578fc61a5f7e..7044db26b1e3a4825667fd0e862f41faa6826fb9 100644 (file)
@@ -405,6 +405,48 @@ static int parse_ip6_addr(int *argc_p, char ***argv_p,
        return res;
 }
 
+static int parse_ether_addr(int *argc_p, char ***argv_p,
+                           struct tc_u32_sel *sel, int off)
+{
+       int res = -1;
+       int argc = *argc_p;
+       char **argv = *argv_p;
+       __u8 addr[6];
+       int offmask = 0;
+       __u32 key;
+       int i;
+
+       if (argc < 1)
+               return -1;
+
+       if (sscanf(*argv, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
+                  addr + 0, addr + 1, addr + 2,
+                  addr + 3, addr + 4, addr + 5) != 6) {
+               fprintf(stderr, "parse_ether_addr: improperly formed address '%s'\n",
+                       *argv);
+               return -1;
+       }
+
+       argc--; argv++;
+       if (argc > 0 && strcmp(argv[0], "at") == 0) {
+               NEXT_ARG();
+               if (parse_at(&argc, &argv, &off, &offmask))
+                       return -1;
+       }
+
+       for (i = 0; i < 6; i += 2) {
+               key = *(__u16 *) (addr + i);
+               
+               res = pack_key16(sel, key, 0xFFFF, off + i, offmask);
+               if (res < 0)
+                       return -1;
+       }
+
+       *argc_p = argc;
+       *argv_p = argv;
+       return res;
+}
+
 static int parse_ip(int *argc_p, char ***argv_p, struct tc_u32_sel *sel)
 {
        int res = -1;
@@ -509,6 +551,31 @@ static int parse_ip6(int *argc_p, char ***argv_p, struct tc_u32_sel *sel)
        return res;
 }
 
+static int parse_ether(int *argc_p, char ***argv_p, struct tc_u32_sel *sel)
+{
+       int res = -1;
+       int argc = *argc_p;
+       char **argv = *argv_p;
+
+       if (argc < 2)
+               return -1;
+
+       if (strcmp(*argv, "src") == 0) {
+               NEXT_ARG();
+               res = parse_ether_addr(&argc, &argv, sel, -8);
+       } else if (strcmp(*argv, "dst") == 0) {
+               NEXT_ARG();
+               res = parse_ether_addr(&argc, &argv, sel, -14);
+       } else {
+               fprintf(stderr, "Unknown match: ether %s\n", *argv);
+               return -1;
+       }
+
+       *argc_p = argc;
+       *argv_p = argv;
+       return res;
+}
+
 #define parse_tcp parse_udp
 static int parse_udp(int *argc_p, char ***argv_p, struct tc_u32_sel *sel)
 {
@@ -629,6 +696,9 @@ static int parse_selector(int *argc_p, char ***argv_p,
        } else if (matches(*argv, "mark") == 0) {
                NEXT_ARG();
                res = parse_mark(&argc, &argv, n);
+       } else if (matches(*argv, "ether") == 0) {
+               NEXT_ARG();
+               res = parse_ether(&argc, &argv, sel);
        } else 
                return -1;