/** * Forward packets to correct output buffers * * Packets, whose destination MAC address is already known from previously * received packets, are forwarded to the matching switch ports. Packets * destined to unknown addresses are broadcasted to all switch ports (except * the ingress port). * * @param pkt_tbl Array of packets * @param num Number of packets in the array * @param thr_arg Thread arguments * @param port_in Input port index */ static inline void forward_packets(odp_packet_t pkt_tbl[], unsigned num, thread_args_t *thr_arg, uint8_t port_in) { odp_packet_t pkt; odph_ethhdr_t *eth; unsigned i; unsigned buf_id; int ret; uint8_t port_out = 0; for (i = 0; i < num; i++) { pkt = pkt_tbl[i]; if (!odp_packet_has_eth(pkt)) { odp_packet_free(pkt); continue; } eth = (odph_ethhdr_t *)odp_packet_l2_ptr(pkt, NULL); /* Lookup source MAC address */ ret = mac_table_get(ð->src, &port_out); /* Update for address table if necessary */ if (ret < 0 || port_out != port_in) mac_table_put(ð->src, port_in); /* Lookup destination MAC address */ ret = mac_table_get(ð->dst, &port_out); if (ret < 0) { /* If address was not found, broadcast packet */ broadcast_packet(pkt, thr_arg, port_in); continue; } buf_id = thr_arg->tx_pktio[port_out].buf.len; thr_arg->tx_pktio[port_out].buf.pkt[buf_id] = pkt; thr_arg->tx_pktio[port_out].buf.len++; } }
/** * Fill packets' eth addresses according to the destination port * * @param pkt_tbl Array of packets * @param num Number of packets in the array * @param dst_port Destination port */ static void fill_eth_addrs(odp_packet_t pkt_tbl[], unsigned num, int dst_port) { odp_packet_t pkt; odph_ethhdr_t *eth; unsigned i; if (!gbl_args->appl.dst_change && !gbl_args->appl.src_change) return; for (i = 0; i < num; ++i) { pkt = pkt_tbl[i]; if (odp_packet_has_eth(pkt)) { eth = (odph_ethhdr_t *)odp_packet_l2_ptr(pkt, NULL); if (gbl_args->appl.src_change) eth->src = gbl_args->port_eth_addr[dst_port]; if (gbl_args->appl.dst_change) eth->dst = gbl_args->dst_eth_addr[dst_port]; } } }