Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 17 additions & 4 deletions ebpf/bypass_filter.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ struct flowv4_keys {
__u8 ip_proto:1;
__u16 vlan0:15;
__u16 vlan1;
__u16 vlan2;
};

struct flowv6_keys {
Expand All @@ -55,6 +56,7 @@ struct flowv6_keys {
__u8 ip_proto:1;
__u16 vlan0:15;
__u16 vlan1;
__u16 vlan2;
};

struct pair {
Expand Down Expand Up @@ -86,7 +88,7 @@ struct vlan_hdr {
*
* \return 0 to drop packet out and -1 to accept it
*/
static __always_inline int ipv4_filter(struct __sk_buff *skb, __u16 vlan0, __u16 vlan1)
static __always_inline int ipv4_filter(struct __sk_buff *skb, __u16 vlan0, __u16 vlan1, __u16 vlan2)
{
__u32 nhoff, verlen;
struct flowv4_keys tuple;
Expand Down Expand Up @@ -120,6 +122,7 @@ static __always_inline int ipv4_filter(struct __sk_buff *skb, __u16 vlan0, __u16
tuple.port16[0] = port;
tuple.vlan0 = vlan0;
tuple.vlan1 = vlan1;
tuple.vlan2 = vlan2;

#if 0
if ((tuple.port16[0] == 22) || (tuple.port16[1] == 22))
Expand Down Expand Up @@ -153,7 +156,7 @@ static __always_inline int ipv4_filter(struct __sk_buff *skb, __u16 vlan0, __u16
*
* \return 0 to drop packet out and -1 to accept it
*/
static __always_inline int ipv6_filter(struct __sk_buff *skb, __u16 vlan0, __u16 vlan1)
static __always_inline int ipv6_filter(struct __sk_buff *skb, __u16 vlan0, __u16 vlan1, __u16 vlan2)
{
__u32 nhoff;
__u8 nhdr;
Expand Down Expand Up @@ -195,6 +198,7 @@ static __always_inline int ipv6_filter(struct __sk_buff *skb, __u16 vlan0, __u16

tuple.vlan0 = vlan0;
tuple.vlan1 = vlan1;
tuple.vlan2 = vlan2;

//char fmt[] = "Now Got IPv6 port %u and %u\n";
//bpf_trace_printk(fmt, sizeof(fmt), tuple.port16[0], tuple.port16[1]);
Expand Down Expand Up @@ -224,6 +228,7 @@ int SEC("filter") hashfilter(struct __sk_buff *skb) {
__u16 proto = load_half(skb, offsetof(struct ethhdr, h_proto));
__u16 vlan0 = skb->vlan_tci & 0x0fff;
__u16 vlan1 = 0;
__u16 vlan2 = 0;

if (proto == ETH_P_8021AD || proto == ETH_P_8021Q) {
proto = load_half(skb, nhoff + offsetof(struct vlan_hdr,
Expand All @@ -235,13 +240,21 @@ int SEC("filter") hashfilter(struct __sk_buff *skb) {
#endif
nhoff += sizeof(struct vlan_hdr);
}
if (proto == ETH_P_8021AD || proto == ETH_P_8021Q) {
proto = load_half(skb, nhoff + offsetof(struct vlan_hdr, h_vlan_encapsulated_proto));
#if VLAN_TRACKING
/* one vlan layer is stripped by OS so get vlan 1 at first pass */
vlan2 = load_half(skb, nhoff + offsetof(struct vlan_hdr, h_vlan_TCI)) & 0x0fff;
#endif
nhoff += sizeof(struct vlan_hdr);
}

skb->cb[0] = nhoff;
switch (proto) {
case ETH_P_IP:
return ipv4_filter(skb, vlan0, vlan1);
return ipv4_filter(skb, vlan0, vlan1, vlan2);
case ETH_P_IPV6:
return ipv6_filter(skb, vlan0, vlan1);
return ipv6_filter(skb, vlan0, vlan1, vlan2);
default:
#if 0
{
Expand Down
29 changes: 25 additions & 4 deletions ebpf/xdp_filter.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ struct flowv4_keys {
__u8 ip_proto:1;
__u16 vlan0:15;
__u16 vlan1;
__u16 vlan2;
};

struct flowv6_keys {
Expand All @@ -88,6 +89,7 @@ struct flowv6_keys {
__u8 ip_proto:1;
__u16 vlan0:15;
__u16 vlan1;
__u16 vlan2;
};

struct pair {
Expand Down Expand Up @@ -232,7 +234,8 @@ static __always_inline int get_dport(void *trans_data, void *data_end,
}
}

static int __always_inline filter_ipv4(struct xdp_md *ctx, void *data, __u64 nh_off, void *data_end, __u16 vlan0, __u16 vlan1)
static int __always_inline filter_ipv4(struct xdp_md *ctx, void *data, __u64 nh_off, void *data_end,
__u16 vlan0, __u16 vlan1, __u16 vlan2)
{
struct iphdr *iph = data + nh_off;
int dport;
Expand Down Expand Up @@ -281,6 +284,7 @@ static int __always_inline filter_ipv4(struct xdp_md *ctx, void *data, __u64 nh_

tuple.vlan0 = vlan0;
tuple.vlan1 = vlan1;
tuple.vlan2 = vlan2;

value = bpf_map_lookup_elem(&flow_table_v4, &tuple);
#if 0
Expand Down Expand Up @@ -376,7 +380,8 @@ static int __always_inline filter_ipv4(struct xdp_md *ctx, void *data, __u64 nh_
#endif
}

static int __always_inline filter_ipv6(struct xdp_md *ctx, void *data, __u64 nh_off, void *data_end, __u16 vlan0, __u16 vlan1)
static int __always_inline filter_ipv6(struct xdp_md *ctx, void *data, __u64 nh_off, void *data_end,
__u16 vlan0, __u16 vlan1, __u16 vlan2)
{
struct ipv6hdr *ip6h = data + nh_off;
int dport;
Expand Down Expand Up @@ -422,6 +427,7 @@ static int __always_inline filter_ipv6(struct xdp_md *ctx, void *data, __u64 nh_

tuple.vlan0 = vlan0;
tuple.vlan1 = vlan1;
tuple.vlan2 = vlan2;

value = bpf_map_lookup_elem(&flow_table_v6, &tuple);
if (value) {
Expand Down Expand Up @@ -491,6 +497,7 @@ int SEC("xdp") xdp_hashfilter(struct xdp_md *ctx)
__u64 nh_off;
__u16 vlan0 = 0;
__u16 vlan1 = 0;
__u16 vlan2 = 0;
#if USE_GLOBAL_BYPASS
int *iface_peer;
char *g_switch = 0;
Expand Down Expand Up @@ -542,11 +549,25 @@ int SEC("xdp") xdp_hashfilter(struct xdp_md *ctx)
vlan1 = 0;
#endif
}
if (h_proto == __constant_htons(ETH_P_8021Q) || h_proto == __constant_htons(ETH_P_8021AD)) {
struct vlan_hdr *vhdr;

vhdr = data + nh_off;
nh_off += sizeof(struct vlan_hdr);
if (data + nh_off > data_end)
return XDP_PASS;
h_proto = vhdr->h_vlan_encapsulated_proto;
#if VLAN_TRACKING
vlan2 = vhdr->h_vlan_TCI & 0x0fff;
#else
vlan2 = 0;
#endif
}

if (h_proto == __constant_htons(ETH_P_IP))
return filter_ipv4(ctx, data, nh_off, data_end, vlan0, vlan1);
return filter_ipv4(ctx, data, nh_off, data_end, vlan0, vlan1, vlan2);
else if (h_proto == __constant_htons(ETH_P_IPV6))
return filter_ipv6(ctx, data, nh_off, data_end, vlan0, vlan1);
return filter_ipv6(ctx, data, nh_off, data_end, vlan0, vlan1, vlan2);

return XDP_PASS;
}
Expand Down
15 changes: 8 additions & 7 deletions src/decode-vxlan.c
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ int DecodeVXLAN(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p,
StatsCounterIncr(&tv->stats, dtv->counter_vxlan);

EthernetHdr *ethh = (EthernetHdr *)(pkt + VXLAN_HEADER_LEN);
int decode_tunnel_proto = DECODE_TUNNEL_UNSET;
bool eth_ok = false;

/* Look at encapsulated Ethernet frame to get next protocol */
uint16_t eth_type = SCNtohs(ethh->eth_type);
Expand All @@ -191,30 +191,31 @@ int DecodeVXLAN(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p,
switch (eth_type) {
case ETHERNET_TYPE_ARP:
SCLogDebug("VXLAN found ARP");
eth_ok = true;
break;
case ETHERNET_TYPE_IP:
SCLogDebug("VXLAN found IPv4");
decode_tunnel_proto = DECODE_TUNNEL_IPV4;
eth_ok = true;
break;
case ETHERNET_TYPE_IPV6:
SCLogDebug("VXLAN found IPv6");
decode_tunnel_proto = DECODE_TUNNEL_IPV6;
eth_ok = true;
break;
case ETHERNET_TYPE_VLAN:
case ETHERNET_TYPE_8021AD:
case ETHERNET_TYPE_8021QINQ:
SCLogDebug("VXLAN found VLAN");
decode_tunnel_proto = DECODE_TUNNEL_VLAN;
eth_ok = true;
break;
default:
SCLogDebug("VXLAN found unsupported Ethertype - expected IPv4, IPv6, VLAN, or ARP");
ENGINE_SET_INVALID_EVENT(p, VXLAN_UNKNOWN_PAYLOAD_TYPE);
}

/* Set-up and process inner packet if it is a supported ethertype */
if (decode_tunnel_proto != DECODE_TUNNEL_UNSET) {
Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + VXLAN_HEADER_LEN + ETHERNET_HEADER_LEN,
len - (VXLAN_HEADER_LEN + ETHERNET_HEADER_LEN), decode_tunnel_proto);
if (eth_ok) {
Packet *tp = PacketTunnelPktSetup(
tv, dtv, p, pkt + VXLAN_HEADER_LEN, len - VXLAN_HEADER_LEN, DECODE_TUNNEL_VXLAN);
if (tp != NULL) {
PKT_SET_SRC(tp, PKT_SRC_DECODER_VXLAN);
PacketEnqueueNoLock(&tv->decode_pq, tp);
Expand Down
6 changes: 4 additions & 2 deletions src/decode.c
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,8 @@ static int DecodeTunnel(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const
return DecodeERSPAN(tv, dtv, p, pkt, len);
case DECODE_TUNNEL_ERSPANI:
return DecodeERSPANTypeI(tv, dtv, p, pkt, len);
case DECODE_TUNNEL_VXLAN:
return DecodeEthernet(tv, dtv, p, pkt, len);
case DECODE_TUNNEL_NSH:
return DecodeNSH(tv, dtv, p, pkt, len);
case DECODE_TUNNEL_ARP:
Expand Down Expand Up @@ -426,7 +428,7 @@ Packet *PacketTunnelPktSetup(ThreadVars *tv, DecodeThreadVars *dtv, Packet *pare
/* set the root ptr to the lowest layer */
if (parent->root != NULL) {
p->root = parent->root;
BUG_ON(parent->ttype != PacketTunnelChild);
BUG_ON(!PacketIsTunnelChild(parent));
} else {
p->root = parent;
parent->ttype = PacketTunnelRoot;
Expand Down Expand Up @@ -487,7 +489,7 @@ Packet *PacketDefragPktSetup(Packet *parent, const uint8_t *pkt, uint32_t len, u
/* set the root ptr to the lowest layer */
if (parent->root != NULL) {
p->root = parent->root;
BUG_ON(parent->ttype != PacketTunnelChild);
BUG_ON(!PacketIsTunnelChild(parent));
} else {
p->root = parent;
// we set parent->ttype later
Expand Down
3 changes: 2 additions & 1 deletion src/decode.h
Original file line number Diff line number Diff line change
Expand Up @@ -550,7 +550,7 @@ typedef struct Packet_
uint32_t flow_hash;

/* tunnel type: none, root or child */
enum PacketTunnelType ttype;
uint8_t ttype; // enum PacketTunnelType
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably also move it to the first cacheline, as there is a 2 byte gap there and this field should also not change after it has been set.

	uint8_t                    proto;                /*    44     1 */
	uint8_t                    recursion_level;      /*    45     1 */
	uint16_t                   vlan_id[3];           /*    46     6 */
	uint8_t                    vlan_idx;             /*    52     1 */
	uint8_t                    flowflags;            /*    53     1 */
	uint8_t                    app_update_direction; /*    54     1 */
	uint8_t                    sig_mask;             /*    55     1 */
	uint16_t                   pkt_hooks;            /*    56     2 */

	/* XXX 2 bytes hole, try to pack */

// MOVE HERE?

	uint32_t                   flags;                /*    60     4 */
	/* --- cacheline 1 boundary (64 bytes) --- */
	struct Flow_ *             flow;                 /*    64     8 */
	uint32_t                   flow_hash;            /*    72     4 */
	uint8_t                    ttype;                /*    76     1 */

	/* XXX 3 bytes hole, try to pack */

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool


SCTime_t ts;

Expand Down Expand Up @@ -1102,6 +1102,7 @@ enum DecodeTunnelProto {
DECODE_TUNNEL_ETHERNET,
DECODE_TUNNEL_ERSPANII,
DECODE_TUNNEL_ERSPANI,
DECODE_TUNNEL_VXLAN,
DECODE_TUNNEL_VLAN,
DECODE_TUNNEL_IPV4,
DECODE_TUNNEL_IPV6,
Expand Down
10 changes: 5 additions & 5 deletions src/log-pcap.c
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ static bool PcapLogCondition(ThreadVars *tv, void *thread_data, const Packet *p)
return false;
}

if (p->ttype == PacketTunnelChild) {
if (PacketIsTunnelChild(p)) {
return false;
}
return true;
Expand Down Expand Up @@ -391,7 +391,7 @@ static int PcapLogOpenHandles(PcapLogData *pl, const Packet *p)
PCAPLOG_PROFILE_START;

int datalink = p->datalink;
if (p->ttype == PacketTunnelChild) {
if (PacketIsTunnelChild(p)) {
Packet *real_p = p->root;
datalink = real_p->datalink;
}
Expand Down Expand Up @@ -627,7 +627,7 @@ static int PcapLog(ThreadVars *tv, void *thread_data, const Packet *p)
pl->pkt_cnt++;
pl->h->ts.tv_sec = SCTIME_SECS(p->ts);
pl->h->ts.tv_usec = SCTIME_USECS(p->ts);
if (p->ttype == PacketTunnelChild) {
if (PacketIsTunnelChild(p)) {
rp = p->root;
pl->h->caplen = GET_PKT_LEN(rp);
pl->h->len = GET_PKT_LEN(rp);
Expand Down Expand Up @@ -701,7 +701,7 @@ static int PcapLog(ThreadVars *tv, void *thread_data, const Packet *p)
/* PcapLogDumpSegment has written over the PcapLogData variables so need to update */
pl->h->ts.tv_sec = SCTIME_SECS(p->ts);
pl->h->ts.tv_usec = SCTIME_USECS(p->ts);
if (p->ttype == PacketTunnelChild) {
if (PacketIsTunnelChild(p)) {
rp = p->root;
pl->h->caplen = GET_PKT_LEN(rp);
pl->h->len = GET_PKT_LEN(rp);
Expand All @@ -714,7 +714,7 @@ static int PcapLog(ThreadVars *tv, void *thread_data, const Packet *p)
}
}

if (p->ttype == PacketTunnelChild) {
if (PacketIsTunnelChild(p)) {
rp = p->root;
ret = PcapWrite(tv, td, GET_PKT_DATA(rp), len);
} else {
Expand Down
12 changes: 12 additions & 0 deletions src/util-ebpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,18 @@ int EBPFLoadFile(const char *iface, const char *path, const char * section,
SCLogError("Too many BPF maps in eBPF files");
break;
}
if (strcmp(bpf_map__name(map), "flow_table_v4") == 0) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See https://github.com/OISF/suricata/pull/14820/changes#r2811731591 I wonder if we should add some magic for padding/alignment...

if (bpf_map__key_size(map) != sizeof(struct flowv4_keys)) {
SCLogError("Incompatible flow_table_v4");
break;
}
}
if (strcmp(bpf_map__name(map), "flow_table_v6") == 0) {
if (bpf_map__key_size(map) != sizeof(struct flowv6_keys)) {
SCLogError("Incompatible flow_table_v6");
break;
}
}
SCLogDebug("Got a map '%s' with fd '%d'", bpf_map__name(map), bpf_map__fd(map));
bpf_map_data->array[bpf_map_data->last].fd = bpf_map__fd(map);
bpf_map_data->array[bpf_map_data->last].name = SCStrdup(bpf_map__name(map));
Expand Down
Loading