Multicast forward of the input packet */
| 298 | |
| 299 | /* Multicast forward of the input packet */ |
| 300 | static inline void |
| 301 | mcast_forward(struct rte_mbuf *m, struct lcore_queue_conf *qconf) |
| 302 | { |
| 303 | struct rte_mbuf *mc; |
| 304 | struct rte_ipv4_hdr *iphdr; |
| 305 | uint32_t dest_addr, port_mask, port_num, use_clone; |
| 306 | int32_t hash; |
| 307 | uint16_t port; |
| 308 | union { |
| 309 | uint64_t as_int; |
| 310 | struct rte_ether_addr as_addr; |
| 311 | } dst_eth_addr; |
| 312 | |
| 313 | /* Remove the Ethernet header from the input packet. 8< */ |
| 314 | iphdr = (struct rte_ipv4_hdr *) |
| 315 | rte_pktmbuf_adj(m, (uint16_t)sizeof(struct rte_ether_hdr)); |
| 316 | RTE_ASSERT(iphdr != NULL); |
| 317 | |
| 318 | dest_addr = rte_be_to_cpu_32(iphdr->dst_addr); |
| 319 | /* >8 End of removing the Ethernet header from the input packet. */ |
| 320 | |
| 321 | /* |
| 322 | * Check that it is a valid multicast address and |
| 323 | * we have some active ports assigned to it. |
| 324 | */ |
| 325 | |
| 326 | /* Check valid multicast address. 8< */ |
| 327 | if (!RTE_IS_IPV4_MCAST(dest_addr) || |
| 328 | (hash = rte_fbk_hash_lookup(mcast_hash, dest_addr)) <= 0 || |
| 329 | (port_mask = hash & enabled_port_mask) == 0) { |
| 330 | rte_pktmbuf_free(m); |
| 331 | return; |
| 332 | } |
| 333 | /* >8 End of valid multicast address check. */ |
| 334 | |
| 335 | /* Calculate number of destination ports. */ |
| 336 | port_num = bitcnt(port_mask); |
| 337 | |
| 338 | /* Should we use rte_pktmbuf_clone() or not. 8< */ |
| 339 | use_clone = (port_num <= MCAST_CLONE_PORTS && |
| 340 | m->nb_segs <= MCAST_CLONE_SEGS); |
| 341 | /* >8 End of using rte_pktmbuf_clone(). */ |
| 342 | |
| 343 | /* Mark all packet's segments as referenced port_num times */ |
| 344 | if (use_clone == 0) |
| 345 | rte_pktmbuf_refcnt_update(m, (uint16_t)port_num); |
| 346 | |
| 347 | /* Construct destination ethernet address. 8< */ |
| 348 | dst_eth_addr.as_int = ETHER_ADDR_FOR_IPV4_MCAST(dest_addr); |
| 349 | /* >8 End of constructing destination ethernet address. */ |
| 350 | |
| 351 | /* Packets dispatched to destination ports. 8< */ |
| 352 | for (port = 0; use_clone != port_mask; port_mask >>= 1, port++) { |
| 353 | |
| 354 | /* Prepare output packet and send it out. */ |
| 355 | if ((port_mask & 1) != 0) { |
| 356 | if (likely ((mc = mcast_out_pkt(m, use_clone)) != NULL)) |
| 357 | mcast_send_pkt(mc, &dst_eth_addr.as_addr, |
no test coverage detected