netfilter: flowtable: add vlan support
[linux-2.6-microblaze.git] / net / netfilter / nft_flow_offload.c
index a6595dc..8392b1a 100644 (file)
@@ -66,6 +66,11 @@ static int nft_dev_fill_forward_path(const struct nf_flow_route *route,
 struct nft_forward_info {
        const struct net_device *indev;
        const struct net_device *outdev;
+       struct id {
+               __u16   id;
+               __be16  proto;
+       } encap[NF_FLOW_TABLE_ENCAP_MAX];
+       u8 num_encaps;
        u8 h_source[ETH_ALEN];
        u8 h_dest[ETH_ALEN];
        enum flow_offload_xmit_type xmit_type;
@@ -84,9 +89,23 @@ static void nft_dev_path_info(const struct net_device_path_stack *stack,
                path = &stack->path[i];
                switch (path->type) {
                case DEV_PATH_ETHERNET:
+               case DEV_PATH_VLAN:
                        info->indev = path->dev;
                        if (is_zero_ether_addr(info->h_source))
                                memcpy(info->h_source, path->dev->dev_addr, ETH_ALEN);
+
+                       if (path->type == DEV_PATH_ETHERNET)
+                               break;
+
+                       /* DEV_PATH_VLAN */
+                       if (info->num_encaps >= NF_FLOW_TABLE_ENCAP_MAX) {
+                               info->indev = NULL;
+                               break;
+                       }
+                       info->outdev = path->dev;
+                       info->encap[info->num_encaps].id = path->encap.id;
+                       info->encap[info->num_encaps].proto = path->encap.proto;
+                       info->num_encaps++;
                        break;
                case DEV_PATH_BRIDGE:
                        if (is_zero_ether_addr(info->h_source))
@@ -94,7 +113,6 @@ static void nft_dev_path_info(const struct net_device_path_stack *stack,
 
                        info->xmit_type = FLOW_OFFLOAD_XMIT_DIRECT;
                        break;
-               case DEV_PATH_VLAN:
                default:
                        info->indev = NULL;
                        break;
@@ -130,6 +148,7 @@ static void nft_dev_forward_path(struct nf_flow_route *route,
        struct net_device_path_stack stack;
        struct nft_forward_info info = {};
        unsigned char ha[ETH_ALEN];
+       int i;
 
        if (nft_dev_fill_forward_path(route, dst, ct, dir, ha, &stack) >= 0)
                nft_dev_path_info(&stack, &info, ha);
@@ -138,6 +157,11 @@ static void nft_dev_forward_path(struct nf_flow_route *route,
                return;
 
        route->tuple[!dir].in.ifindex = info.indev->ifindex;
+       for (i = 0; i < info.num_encaps; i++) {
+               route->tuple[!dir].in.encap[i].id = info.encap[i].id;
+               route->tuple[!dir].in.encap[i].proto = info.encap[i].proto;
+       }
+       route->tuple[!dir].in.num_encaps = info.num_encaps;
 
        if (info.xmit_type == FLOW_OFFLOAD_XMIT_DIRECT) {
                memcpy(route->tuple[dir].out.h_source, info.h_source, ETH_ALEN);