#include "bpf_helpers.h"
+/* vlan tracking: set it to 0 if you don't use VLAN for flow tracking */
+#define VLAN_TRACKING 1
+
#define LINUX_VERSION_CODE 263682
struct flowv4_keys {
.max_entries = 32768,
};
+struct vlan_hdr {
+ __u16 h_vlan_TCI;
+ __u16 h_vlan_encapsulated_proto;
+};
+
/**
* IPv4 filter
*
* \return 0 to drop packet out and -1 to accept it
*/
-static __always_inline int ipv4_filter(struct __sk_buff *skb)
+static __always_inline int ipv4_filter(struct __sk_buff *skb, __u16 vlan0, __u16 vlan1)
{
__u32 nhoff, verlen;
struct flowv4_keys tuple;
struct pair *value;
__u16 port;
- __u16 vlan_id = skb->vlan_tci & 0x0fff;
nhoff = skb->cb[0];
port = tuple.port16[1];
tuple.port16[1] = tuple.port16[0];
tuple.port16[0] = port;
- tuple.vlan_id[0] = vlan_id;
- /* FIXME add second vlan layer */
- tuple.vlan_id[1] = 0;
+ tuple.vlan_id[0] = vlan0;
+ tuple.vlan_id[1] = vlan1;
#if 0
if ((tuple.port16[0] == 22) || (tuple.port16[1] == 22))
*
* \return 0 to drop packet out and -1 to accept it
*/
-static __always_inline int ipv6_filter(struct __sk_buff *skb)
+static __always_inline int ipv6_filter(struct __sk_buff *skb, __u16 vlan0, __u16 vlan1)
{
__u32 nhoff;
__u8 nhdr;
struct flowv6_keys tuple;
struct pair *value;
__u16 port;
- __u16 vlan_id = skb->vlan_tci & 0x0fff;
nhoff = skb->cb[0];
tuple.port16[0] = port;
tuple.ip_proto = nhdr;
- tuple.vlan_id[0] = vlan_id;
- /* FIXME add second vlan layer */
- tuple.vlan_id[1] = 0;
+ tuple.vlan_id[0] = vlan0;
+ tuple.vlan_id[1] = vlan1;
//char fmt[] = "Now Got IPv6 port %u and %u\n";
//bpf_trace_printk(fmt, sizeof(fmt), tuple.port16[0], tuple.port16[1]);
int SEC("filter") hashfilter(struct __sk_buff *skb) {
__u32 nhoff = ETH_HLEN;
+ void *data = (void *)(long)skb->data;
+ void *data_end = (void *)(long)skb->data_end;
+ __u64 proto = load_half(skb, 12);
+ __u16 vlan0 = 0;
+ __u16 vlan1 = 0;
+
+ if (proto == ETH_P_8021AD) {
+ proto = load_half(skb, nhoff + offsetof(struct vlan_hdr,
+ h_vlan_encapsulated_proto));
+#if VLAN_TRACKING
+ if (data + nhoff <= data_end) {
+ vlan0 = ((struct vlan_hdr *)(data + nhoff))->h_vlan_TCI & 0x0fff;
+ }
+#endif
+ nhoff += sizeof(struct vlan_hdr);
+ }
+
+ if (proto == ETH_P_8021Q) {
+ proto = load_half(skb, nhoff + offsetof(struct vlan_hdr,
+ h_vlan_encapsulated_proto));
+#if VLAN_TRACKING
+ if (data + nhoff <= data_end) {
+ vlan1 = ((struct vlan_hdr *)(data + nhoff))->h_vlan_TCI & 0x0fff;
+ }
+#endif
+ nhoff += sizeof(struct vlan_hdr);
+ }
skb->cb[0] = nhoff;
switch (skb->protocol) {
case __constant_htons(ETH_P_IP):
- return ipv4_filter(skb);
+ return ipv4_filter(skb, vlan0, vlan1);
case __constant_htons(ETH_P_IPV6):
- return ipv6_filter(skb);
+ return ipv6_filter(skb, vlan0, vlan1);
default:
#if 0
{