Skip to content

Commit 3b3a5b0

Browse files
wdebruijdavem330
authored andcommitted
packet: rollover huge flows before small flows
Migrate flows from a socket to another socket in the fanout group not only when the socket is full. Start migrating huge flows early, to divert possible 4-tuple attacks without affecting normal traffic. Introduce fanout_flow_is_huge(). This detects huge flows, which are defined as taking up more than half the load. It does so cheaply, by storing the rxhashes of the N most recent packets. If over half of these are the same rxhash as the current packet, then drop it. This only protects against 4-tuple attacks. N is chosen to fit all data in a single cache line. Tested: Ran bench_rollover for 10 sec with 1.5 Mpps of single flow input. lpbb5:/export/hda3/willemb# ./bench_rollover -l 1000 -r -s cpu rx rx.k drop.k rollover r.huge r.failed 0 14 14 0 0 0 0 1 20 20 0 0 0 0 2 16 16 0 0 0 0 3 6168824 6168824 0 4867721 4867721 0 4 4867741 4867741 0 0 0 0 5 12 12 0 0 0 0 6 15 15 0 0 0 0 7 17 17 0 0 0 0 Signed-off-by: Willem de Bruijn <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 2ccdbaa commit 3b3a5b0

File tree

2 files changed

+24
-3
lines changed

2 files changed

+24
-3
lines changed

net/packet/af_packet.c

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1341,6 +1341,20 @@ static int fanout_rr_next(struct packet_fanout *f, unsigned int num)
13411341
return x;
13421342
}
13431343

1344+
static bool fanout_flow_is_huge(struct packet_sock *po, struct sk_buff *skb)
1345+
{
1346+
u32 rxhash;
1347+
int i, count = 0;
1348+
1349+
rxhash = skb_get_hash(skb);
1350+
for (i = 0; i < ROLLOVER_HLEN; i++)
1351+
if (po->rollover->history[i] == rxhash)
1352+
count++;
1353+
1354+
po->rollover->history[prandom_u32() % ROLLOVER_HLEN] = rxhash;
1355+
return count > (ROLLOVER_HLEN >> 1);
1356+
}
1357+
13441358
static unsigned int fanout_demux_hash(struct packet_fanout *f,
13451359
struct sk_buff *skb,
13461360
unsigned int num)
@@ -1381,11 +1395,16 @@ static unsigned int fanout_demux_rollover(struct packet_fanout *f,
13811395
unsigned int num)
13821396
{
13831397
struct packet_sock *po, *po_next;
1384-
unsigned int i, j;
1398+
unsigned int i, j, room;
13851399

13861400
po = pkt_sk(f->arr[idx]);
1387-
if (try_self && packet_rcv_has_room(po, skb) != ROOM_NONE)
1388-
return idx;
1401+
1402+
if (try_self) {
1403+
room = packet_rcv_has_room(po, skb);
1404+
if (room == ROOM_NORMAL ||
1405+
(room == ROOM_LOW && !fanout_flow_is_huge(po, skb)))
1406+
return idx;
1407+
}
13891408

13901409
i = j = min_t(int, po->rollover->sock, num - 1);
13911410
do {

net/packet/internal.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ struct packet_fanout {
8989

9090
struct packet_rollover {
9191
int sock;
92+
#define ROLLOVER_HLEN (L1_CACHE_BYTES / sizeof(u32))
93+
u32 history[ROLLOVER_HLEN] ____cacheline_aligned;
9294
} ____cacheline_aligned_in_smp;
9395

9496
struct packet_sock {

0 commit comments

Comments
 (0)