| 77 | } |
| 78 | |
| 79 | void VXLANEncap::ProcessBatch(Context *ctx, bess::PacketBatch *batch) { |
| 80 | using bess::utils::Ethernet; |
| 81 | using bess::utils::Ipv4; |
| 82 | using bess::utils::Udp; |
| 83 | using bess::utils::Vxlan; |
| 84 | |
| 85 | int cnt = batch->cnt(); |
| 86 | |
| 87 | for (int i = 0; i < cnt; i++) { |
| 88 | bess::Packet *pkt = batch->pkts()[i]; |
| 89 | |
| 90 | be32_t ip_src = get_attr<be32_t>(this, ATTR_R_TUN_IP_SRC, pkt); |
| 91 | be32_t ip_dst = get_attr<be32_t>(this, ATTR_R_TUN_IP_DST, pkt); |
| 92 | be32_t vni = get_attr<be32_t>(this, ATTR_R_TUN_ID, pkt); |
| 93 | |
| 94 | Ethernet *inner_eth; |
| 95 | Udp *udp; |
| 96 | Vxlan *vh; |
| 97 | |
| 98 | size_t inner_frame_len = pkt->total_len() + sizeof(*udp); |
| 99 | |
| 100 | inner_eth = pkt->head_data<Ethernet *>(); |
| 101 | udp = static_cast<Udp *>(pkt->prepend(sizeof(*udp) + sizeof(*vh))); |
| 102 | if (unlikely(!udp)) { |
| 103 | continue; |
| 104 | } |
| 105 | |
| 106 | vh = reinterpret_cast<Vxlan *>(udp + 1); |
| 107 | vh->vx_flags = be32_t(0x08000000); |
| 108 | vh->vx_vni = vni << 8; |
| 109 | |
| 110 | udp->src_port = be16_t( |
| 111 | rte_hash_crc(inner_eth, sizeof(Ethernet::Address) * 2, UINT32_MAX) | |
| 112 | 0xf000); |
| 113 | udp->dst_port = dstport_; |
| 114 | udp->length = be16_t(sizeof(*udp) + inner_frame_len); |
| 115 | udp->checksum = 0; |
| 116 | |
| 117 | set_attr<be32_t>(this, ATTR_W_IP_SRC, pkt, ip_src); |
| 118 | set_attr<be32_t>(this, ATTR_W_IP_DST, pkt, ip_dst); |
| 119 | set_attr<uint8_t>(this, ATTR_W_IP_PROTO, pkt, Ipv4::Proto::kUdp); |
| 120 | } |
| 121 | |
| 122 | RunNextModule(ctx, batch); |
| 123 | } |
| 124 | |
| 125 | ADD_MODULE(VXLANEncap, "vxlan_encap", |
| 126 | "encapsulates packets with UDP/VXLAN headers") |