diff options
author | Jesse Gross <jesse@nicira.com> | 2014-12-30 22:10:15 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-01-02 15:46:41 -0500 |
commit | 9b174d88c257150562b0101fcc6cb6c3cb74275c (patch) | |
tree | 345b03321802cb222991d9c3a524064eadbb54ad /net | |
parent | 05930b5ec1d3b2a5c76e1959b54cae15587009c7 (diff) |
net: Add Transparent Ethernet Bridging GRO support.
Currently the only tunnel protocol that supports GRO with encapsulated
Ethernet is VXLAN. This pulls out the Ethernet code into a proper layer
so that it can be used by other tunnel protocols such as GRE and Geneve.
Signed-off-by: Jesse Gross <jesse@nicira.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/ethernet/eth.c | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c index 33a140e15834..238f38d21641 100644 --- a/net/ethernet/eth.c +++ b/net/ethernet/eth.c | |||
@@ -424,3 +424,95 @@ ssize_t sysfs_format_mac(char *buf, const unsigned char *addr, int len) | |||
424 | return scnprintf(buf, PAGE_SIZE, "%*phC\n", len, addr); | 424 | return scnprintf(buf, PAGE_SIZE, "%*phC\n", len, addr); |
425 | } | 425 | } |
426 | EXPORT_SYMBOL(sysfs_format_mac); | 426 | EXPORT_SYMBOL(sysfs_format_mac); |
427 | |||
428 | struct sk_buff **eth_gro_receive(struct sk_buff **head, | ||
429 | struct sk_buff *skb) | ||
430 | { | ||
431 | struct sk_buff *p, **pp = NULL; | ||
432 | struct ethhdr *eh, *eh2; | ||
433 | unsigned int hlen, off_eth; | ||
434 | const struct packet_offload *ptype; | ||
435 | __be16 type; | ||
436 | int flush = 1; | ||
437 | |||
438 | off_eth = skb_gro_offset(skb); | ||
439 | hlen = off_eth + sizeof(*eh); | ||
440 | eh = skb_gro_header_fast(skb, off_eth); | ||
441 | if (skb_gro_header_hard(skb, hlen)) { | ||
442 | eh = skb_gro_header_slow(skb, hlen, off_eth); | ||
443 | if (unlikely(!eh)) | ||
444 | goto out; | ||
445 | } | ||
446 | |||
447 | flush = 0; | ||
448 | |||
449 | for (p = *head; p; p = p->next) { | ||
450 | if (!NAPI_GRO_CB(p)->same_flow) | ||
451 | continue; | ||
452 | |||
453 | eh2 = (struct ethhdr *)(p->data + off_eth); | ||
454 | if (compare_ether_header(eh, eh2)) { | ||
455 | NAPI_GRO_CB(p)->same_flow = 0; | ||
456 | continue; | ||
457 | } | ||
458 | } | ||
459 | |||
460 | type = eh->h_proto; | ||
461 | |||
462 | rcu_read_lock(); | ||
463 | ptype = gro_find_receive_by_type(type); | ||
464 | if (ptype == NULL) { | ||
465 | flush = 1; | ||
466 | goto out_unlock; | ||
467 | } | ||
468 | |||
469 | skb_gro_pull(skb, sizeof(*eh)); | ||
470 | skb_gro_postpull_rcsum(skb, eh, sizeof(*eh)); | ||
471 | pp = ptype->callbacks.gro_receive(head, skb); | ||
472 | |||
473 | out_unlock: | ||
474 | rcu_read_unlock(); | ||
475 | out: | ||
476 | NAPI_GRO_CB(skb)->flush |= flush; | ||
477 | |||
478 | return pp; | ||
479 | } | ||
480 | EXPORT_SYMBOL(eth_gro_receive); | ||
481 | |||
482 | int eth_gro_complete(struct sk_buff *skb, int nhoff) | ||
483 | { | ||
484 | struct ethhdr *eh = (struct ethhdr *)(skb->data + nhoff); | ||
485 | __be16 type = eh->h_proto; | ||
486 | struct packet_offload *ptype; | ||
487 | int err = -ENOSYS; | ||
488 | |||
489 | if (skb->encapsulation) | ||
490 | skb_set_inner_mac_header(skb, nhoff); | ||
491 | |||
492 | rcu_read_lock(); | ||
493 | ptype = gro_find_complete_by_type(type); | ||
494 | if (ptype != NULL) | ||
495 | err = ptype->callbacks.gro_complete(skb, nhoff + | ||
496 | sizeof(struct ethhdr)); | ||
497 | |||
498 | rcu_read_unlock(); | ||
499 | return err; | ||
500 | } | ||
501 | EXPORT_SYMBOL(eth_gro_complete); | ||
502 | |||
503 | static struct packet_offload eth_packet_offload __read_mostly = { | ||
504 | .type = cpu_to_be16(ETH_P_TEB), | ||
505 | .callbacks = { | ||
506 | .gro_receive = eth_gro_receive, | ||
507 | .gro_complete = eth_gro_complete, | ||
508 | }, | ||
509 | }; | ||
510 | |||
511 | static int __init eth_offload_init(void) | ||
512 | { | ||
513 | dev_add_offload(ð_packet_offload); | ||
514 | |||
515 | return 0; | ||
516 | } | ||
517 | |||
518 | fs_initcall(eth_offload_init); | ||