flow: take vlan_id's into account in the flow hash

In VLAN we can have 2 layers of encapsulation. In this patch both
layers are used in the flow hash to distinguish between encapsulated
traffic.
pull/460/head
Victor Julien 14 years ago
parent 055b422c28
commit 58ed1f2411

@ -132,6 +132,7 @@ enum {
/* VLAN EVENTS */ /* VLAN EVENTS */
VLAN_HEADER_TOO_SMALL, /**< vlan header smaller than minimum size */ VLAN_HEADER_TOO_SMALL, /**< vlan header smaller than minimum size */
VLAN_UNKNOWN_TYPE, /**< vlan unknown type */ VLAN_UNKNOWN_TYPE, /**< vlan unknown type */
VLAN_HEADER_TOO_MANY_LAYERS,
/* RAW EVENTS */ /* RAW EVENTS */
IPRAW_INVALID_IPV, /**< invalid ip version in ip raw */ IPRAW_INVALID_IPV, /**< invalid ip version in ip raw */

@ -54,21 +54,33 @@
*/ */
void DecodeVLAN(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t len, PacketQueue *pq) void DecodeVLAN(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t len, PacketQueue *pq)
{ {
uint32_t proto;
SCPerfCounterIncr(dtv->counter_vlan, tv->sc_perf_pca); SCPerfCounterIncr(dtv->counter_vlan, tv->sc_perf_pca);
if(len < VLAN_HEADER_LEN) { if(len < VLAN_HEADER_LEN) {
ENGINE_SET_EVENT(p,VLAN_HEADER_TOO_SMALL); ENGINE_SET_EVENT(p,VLAN_HEADER_TOO_SMALL);
return; return;
} }
if (p->vlan_idx >= 2) {
ENGINE_SET_EVENT(p,VLAN_HEADER_TOO_MANY_LAYERS);
return;
}
p->vlanh = (VLANHdr *)pkt; p->vlanh[p->vlan_idx] = (VLANHdr *)pkt;
if(p->vlanh == NULL) if(p->vlanh[p->vlan_idx] == NULL)
return; return;
proto = GET_VLAN_PROTO(p->vlanh[p->vlan_idx]);
SCLogDebug("p %p pkt %p VLAN protocol %04x VLAN PRI %d VLAN CFI %d VLAN ID %d Len: %" PRId32 "", SCLogDebug("p %p pkt %p VLAN protocol %04x VLAN PRI %d VLAN CFI %d VLAN ID %d Len: %" PRId32 "",
p, pkt, GET_VLAN_PROTO(p->vlanh), GET_VLAN_PRIORITY(p->vlanh), GET_VLAN_CFI(p->vlanh), GET_VLAN_ID(p->vlanh), len); p, pkt, proto, GET_VLAN_PRIORITY(p->vlanh[p->vlan_idx]),
GET_VLAN_CFI(p->vlanh[p->vlan_idx]), GET_VLAN_ID(p->vlanh[p->vlan_idx]), len);
p->vlan_id[p->vlan_idx] = (uint16_t)GET_VLAN_ID(p->vlanh[p->vlan_idx]);
p->vlan_idx++;
switch (GET_VLAN_PROTO(p->vlanh)) { switch (proto) {
case ETHERNET_TYPE_IP: case ETHERNET_TYPE_IP:
DecodeIPV4(tv, dtv, p, pkt + VLAN_HEADER_LEN, DecodeIPV4(tv, dtv, p, pkt + VLAN_HEADER_LEN,
len - VLAN_HEADER_LEN, pq); len - VLAN_HEADER_LEN, pq);
@ -86,11 +98,16 @@ void DecodeVLAN(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt,
len - VLAN_HEADER_LEN, pq); len - VLAN_HEADER_LEN, pq);
break; break;
case ETHERNET_TYPE_VLAN: case ETHERNET_TYPE_VLAN:
DecodeVLAN(tv, dtv, p, pkt + VLAN_HEADER_LEN, if (p->vlan_idx >= 2) {
len - VLAN_HEADER_LEN, pq); ENGINE_SET_EVENT(p,VLAN_HEADER_TOO_MANY_LAYERS);
return;
} else {
DecodeVLAN(tv, dtv, p, pkt + VLAN_HEADER_LEN,
len - VLAN_HEADER_LEN, pq);
}
break; break;
default: default:
SCLogDebug("unknown VLAN type: %" PRIx32 "",GET_VLAN_PROTO(p->vlanh)); SCLogDebug("unknown VLAN type: %" PRIx32 "", proto);
ENGINE_SET_EVENT(p,VLAN_UNKNOWN_TYPE); ENGINE_SET_EVENT(p,VLAN_UNKNOWN_TYPE);
return; return;
} }

@ -367,6 +367,9 @@ typedef struct Packet_
* has the exact same tuple as the lower levels */ * has the exact same tuple as the lower levels */
uint8_t recursion_level; uint8_t recursion_level;
uint16_t vlan_id[2];
uint8_t vlan_idx;
/* Pkt Flags */ /* Pkt Flags */
uint32_t flags; uint32_t flags;
@ -442,7 +445,7 @@ typedef struct Packet_
GREHdr *greh; GREHdr *greh;
VLANHdr *vlanh; VLANHdr *vlanh[2];
/* ptr to the payload of the packet /* ptr to the payload of the packet
* with it's length. */ * with it's length. */
@ -634,6 +637,9 @@ typedef struct DecodeThreadVars_
(p)->flags = (p)->flags & PKT_ALLOC; \ (p)->flags = (p)->flags & PKT_ALLOC; \
(p)->flowflags = 0; \ (p)->flowflags = 0; \
(p)->pkt_src = 0; \ (p)->pkt_src = 0; \
(p)->vlan_id[0] = 0; \
(p)->vlan_id[1] = 0; \
(p)->vlan_idx = 0; \
FlowDeReference(&((p)->flow)); \ FlowDeReference(&((p)->flow)); \
(p)->ts.tv_sec = 0; \ (p)->ts.tv_sec = 0; \
(p)->ts.tv_usec = 0; \ (p)->ts.tv_usec = 0; \
@ -669,7 +675,8 @@ typedef struct DecodeThreadVars_
(p)->pppoesh = NULL; \ (p)->pppoesh = NULL; \
(p)->pppoedh = NULL; \ (p)->pppoedh = NULL; \
(p)->greh = NULL; \ (p)->greh = NULL; \
(p)->vlanh = NULL; \ (p)->vlanh[0] = NULL; \
(p)->vlanh[1] = NULL; \
(p)->payload = NULL; \ (p)->payload = NULL; \
(p)->payload_len = 0; \ (p)->payload_len = 0; \
(p)->pktlen = 0; \ (p)->pktlen = 0; \

@ -117,6 +117,7 @@ struct DetectEngineEvents_ {
{ "ipraw.invalid_ip_version",IPRAW_INVALID_IPV, }, { "ipraw.invalid_ip_version",IPRAW_INVALID_IPV, },
{ "vlan.header_too_small",VLAN_HEADER_TOO_SMALL, }, { "vlan.header_too_small",VLAN_HEADER_TOO_SMALL, },
{ "vlan.unknown_type",VLAN_UNKNOWN_TYPE, }, { "vlan.unknown_type",VLAN_UNKNOWN_TYPE, },
{ "vlan.too_many_layers", VLAN_HEADER_TOO_MANY_LAYERS, },
{ "ipv4.frag_too_large", IPV4_FRAG_PKT_TOO_LARGE, }, { "ipv4.frag_too_large", IPV4_FRAG_PKT_TOO_LARGE, },
{ "ipv4.frag_overlap", IPV4_FRAG_OVERLAP, }, { "ipv4.frag_overlap", IPV4_FRAG_OVERLAP, },
{ "ipv6.frag_too_large", IPV6_FRAG_PKT_TOO_LARGE, }, { "ipv6.frag_too_large", IPV6_FRAG_PKT_TOO_LARGE, },

@ -172,8 +172,9 @@ typedef struct FlowHashKey4_ {
uint16_t sp, dp; uint16_t sp, dp;
uint16_t proto; /**< u16 so proto and recur add up to u32 */ uint16_t proto; /**< u16 so proto and recur add up to u32 */
uint16_t recur; /**< u16 so proto and recur add up to u32 */ uint16_t recur; /**< u16 so proto and recur add up to u32 */
uint16_t vlan_id[2];
}; };
uint32_t u32[4]; const uint32_t u32[5];
}; };
} FlowHashKey4; } FlowHashKey4;
@ -184,8 +185,9 @@ typedef struct FlowHashKey6_ {
uint16_t sp, dp; uint16_t sp, dp;
uint16_t proto; /**< u16 so proto and recur add up to u32 */ uint16_t proto; /**< u16 so proto and recur add up to u32 */
uint16_t recur; /**< u16 so proto and recur add up to u32 */ uint16_t recur; /**< u16 so proto and recur add up to u32 */
uint16_t vlan_id[2];
}; };
uint32_t u32[10]; const uint32_t u32[11];
}; };
} FlowHashKey6; } FlowHashKey6;
@ -224,8 +226,10 @@ static inline uint32_t FlowGetKey(Packet *p) {
} }
fhk.proto = (uint16_t)p->proto; fhk.proto = (uint16_t)p->proto;
fhk.recur = (uint16_t)p->recursion_level; fhk.recur = (uint16_t)p->recursion_level;
fhk.vlan_id[0] = p->vlan_id[0];
fhk.vlan_id[1] = p->vlan_id[1];
uint32_t hash = hashword(fhk.u32, 4, flow_config.hash_rand); uint32_t hash = hashword(fhk.u32, 5, flow_config.hash_rand);
key = hash % flow_config.hash_size; key = hash % flow_config.hash_size;
} else if (ICMPV4_DEST_UNREACH_IS_VALID(p)) { } else if (ICMPV4_DEST_UNREACH_IS_VALID(p)) {
@ -248,8 +252,10 @@ static inline uint32_t FlowGetKey(Packet *p) {
} }
fhk.proto = (uint16_t)ICMPV4_GET_EMB_PROTO(p); fhk.proto = (uint16_t)ICMPV4_GET_EMB_PROTO(p);
fhk.recur = (uint16_t)p->recursion_level; fhk.recur = (uint16_t)p->recursion_level;
fhk.vlan_id[0] = p->vlan_id[0];
fhk.vlan_id[1] = p->vlan_id[1];
uint32_t hash = hashword(fhk.u32, 4, flow_config.hash_rand); uint32_t hash = hashword(fhk.u32, 5, flow_config.hash_rand);
key = hash % flow_config.hash_size; key = hash % flow_config.hash_size;
} else { } else {
@ -265,8 +271,10 @@ static inline uint32_t FlowGetKey(Packet *p) {
fhk.dp = 0xbeef; fhk.dp = 0xbeef;
fhk.proto = (uint16_t)p->proto; fhk.proto = (uint16_t)p->proto;
fhk.recur = (uint16_t)p->recursion_level; fhk.recur = (uint16_t)p->recursion_level;
fhk.vlan_id[0] = p->vlan_id[0];
fhk.vlan_id[1] = p->vlan_id[1];
uint32_t hash = hashword(fhk.u32, 4, flow_config.hash_rand); uint32_t hash = hashword(fhk.u32, 5, flow_config.hash_rand);
key = hash % flow_config.hash_size; key = hash % flow_config.hash_size;
} }
} else if (p->ip6h != NULL) { } else if (p->ip6h != NULL) {
@ -299,8 +307,10 @@ static inline uint32_t FlowGetKey(Packet *p) {
} }
fhk.proto = (uint16_t)p->proto; fhk.proto = (uint16_t)p->proto;
fhk.recur = (uint16_t)p->recursion_level; fhk.recur = (uint16_t)p->recursion_level;
fhk.vlan_id[0] = p->vlan_id[0];
fhk.vlan_id[1] = p->vlan_id[1];
uint32_t hash = hashword(fhk.u32, 10, flow_config.hash_rand); uint32_t hash = hashword(fhk.u32, 11, flow_config.hash_rand);
key = hash % flow_config.hash_size; key = hash % flow_config.hash_size;
} else } else
key = 0; key = 0;
@ -318,7 +328,9 @@ static inline uint32_t FlowGetKey(Packet *p) {
CMP_ADDR(&(f1)->dst, &(f2)->src) && \ CMP_ADDR(&(f1)->dst, &(f2)->src) && \
CMP_PORT((f1)->sp, (f2)->dp) && CMP_PORT((f1)->dp, (f2)->sp))) && \ CMP_PORT((f1)->sp, (f2)->dp) && CMP_PORT((f1)->dp, (f2)->sp))) && \
(f1)->proto == (f2)->proto && \ (f1)->proto == (f2)->proto && \
(f1)->recursion_level == (f2)->recursion_level) (f1)->recursion_level == (f2)->recursion_level && \
(f1)->vlan_id[0] == (f2)->vlan_id[0] && \
(f1)->vlan_id[1] == (f2)->vlan_id[1])
/** /**
* \brief See if a ICMP packet belongs to a flow by comparing the embedded * \brief See if a ICMP packet belongs to a flow by comparing the embedded
@ -340,7 +352,9 @@ static inline int FlowCompareICMPv4(Flow *f, Packet *p) {
f->sp == p->icmpv4vars.emb_sport && f->sp == p->icmpv4vars.emb_sport &&
f->dp == p->icmpv4vars.emb_dport && f->dp == p->icmpv4vars.emb_dport &&
f->proto == ICMPV4_GET_EMB_PROTO(p) && f->proto == ICMPV4_GET_EMB_PROTO(p) &&
f->recursion_level == p->recursion_level) f->recursion_level == p->recursion_level &&
f->vlan_id[0] == p->vlan_id[0] &&
f->vlan_id[1] == p->vlan_id[1])
{ {
return 1; return 1;
@ -351,7 +365,9 @@ static inline int FlowCompareICMPv4(Flow *f, Packet *p) {
f->dp == p->icmpv4vars.emb_sport && f->dp == p->icmpv4vars.emb_sport &&
f->sp == p->icmpv4vars.emb_dport && f->sp == p->icmpv4vars.emb_dport &&
f->proto == ICMPV4_GET_EMB_PROTO(p) && f->proto == ICMPV4_GET_EMB_PROTO(p) &&
f->recursion_level == p->recursion_level) f->recursion_level == p->recursion_level &&
f->vlan_id[0] == p->vlan_id[0] &&
f->vlan_id[1] == p->vlan_id[1])
{ {
return 1; return 1;
} }

@ -110,6 +110,8 @@ void FlowInit(Flow *f, Packet *p)
f->proto = p->proto; f->proto = p->proto;
f->recursion_level = p->recursion_level; f->recursion_level = p->recursion_level;
f->vlan_id[0] = p->vlan_id[0];
f->vlan_id[1] = p->vlan_id[1];
if (PKT_IS_IPV4(p)) { if (PKT_IS_IPV4(p)) {
FLOW_SET_IPV4_SRC_ADDR_FROM_PACKET(p, &f->src); FLOW_SET_IPV4_SRC_ADDR_FROM_PACKET(p, &f->src);

@ -280,6 +280,7 @@ typedef struct Flow_
}; };
uint8_t proto; uint8_t proto;
uint8_t recursion_level; uint8_t recursion_level;
uint16_t vlan_id[2];
/* end of flow "header" */ /* end of flow "header" */

Loading…
Cancel
Save