| 49 | } |
| 50 | |
| 51 | void MPLSPop::ProcessBatch(Context *ctx, bess::PacketBatch *batch) { |
| 52 | int cnt = batch->cnt(); |
| 53 | |
| 54 | for (int i = 0; i < cnt; i++) { |
| 55 | bess::Packet *pkt = batch->pkts()[i]; |
| 56 | |
| 57 | Ethernet *eth = pkt->head_data<Ethernet *>(); |
| 58 | |
| 59 | if (eth->ether_type != be16_t(Ethernet::Type::kMpls)) { |
| 60 | // non MPLS packets are sent to different output gate |
| 61 | EmitPacket(ctx, pkt, 1); |
| 62 | continue; |
| 63 | } |
| 64 | |
| 65 | // TODO(gsagie) save the MPLS label as metadata |
| 66 | // Mpls *mpls = reinterpret_cast<Mpls *>(eth_header + 1); |
| 67 | |
| 68 | // TODO(gsagie) convert this to be more efficient using Intel instructions |
| 69 | if (remove_eth_header_) { |
| 70 | pkt->adj(sizeof(Ethernet) + sizeof(Mpls)); |
| 71 | } else { |
| 72 | Ethernet::Address src_addr = eth->src_addr; |
| 73 | Ethernet::Address dst_addr = eth->dst_addr; |
| 74 | |
| 75 | pkt->adj(sizeof(Mpls)); |
| 76 | Ethernet *eth_new = pkt->head_data<Ethernet *>(); |
| 77 | eth_new->src_addr = src_addr; |
| 78 | eth_new->dst_addr = dst_addr; |
| 79 | eth_new->ether_type = next_ether_type_; |
| 80 | } |
| 81 | EmitPacket(ctx, pkt, 0); |
| 82 | } |
| 83 | } |
| 84 | |
| 85 | CommandResponse MPLSPop::CommandSet(const bess::pb::MplsPopArg &arg) { |
| 86 | remove_eth_header_ = arg.remove_eth_header(); |