unsigned int vr_reinject_packet(struct vr_packet *pkt, struct vr_forwarding_md *fmd) { struct vr_interface *vif = pkt->vp_if; int handled; if (pkt->vp_nh) { /* If nexthop does not have valid data, drop it */ if (!(pkt->vp_nh->nh_flags & NH_FLAG_VALID)) { vr_pfree(pkt, VP_DROP_INVALID_NH); return 0; } return pkt->vp_nh->nh_reach_nh(pkt, pkt->vp_nh, fmd); } if (vif_is_vhost(vif)) { handled = vr_l3_input(pkt, fmd); if (!handled) vif_drop_pkt(vif, pkt, 1); return 0; } return vr_bridge_input(vif->vif_router, pkt, fmd); }
static void vr_arp_proxy(struct vr_arp *sarp, struct vr_packet *pkt, struct vr_forwarding_md *fmd, unsigned char *dmac) { struct vr_eth *eth; struct vr_arp *arp; struct vr_forwarding_md fmd_new; struct vr_interface *vif = pkt->vp_if; eth = (struct vr_eth *)pkt_push(pkt, sizeof(*eth)); if (!eth) { vr_pfree(pkt, VP_DROP_PUSH); return; } memcpy(eth->eth_dmac, sarp->arp_sha, VR_ETHER_ALEN); memcpy(eth->eth_smac, dmac, VR_ETHER_ALEN); eth->eth_proto = htons(VR_ETH_PROTO_ARP); arp = (struct vr_arp *)(pkt_data(pkt) + sizeof(*eth)); arp->arp_hw = htons(VR_ARP_HW_TYPE_ETHER); arp->arp_proto = htons(VR_ETH_PROTO_IP); arp->arp_hwlen = VR_ETHER_ALEN; arp->arp_protolen = VR_IP_ADDRESS_LEN; arp->arp_op = htons(VR_ARP_OP_REPLY); memcpy(arp->arp_sha, dmac, VR_ETHER_ALEN); memcpy(arp->arp_dha, sarp->arp_sha, VR_ETHER_ALEN); memcpy(&arp->arp_dpa, &sarp->arp_spa, sizeof(sarp->arp_spa)); memcpy(&arp->arp_spa, &sarp->arp_dpa, sizeof(sarp->arp_dpa)); vr_init_forwarding_md(&fmd_new); fmd_new.fmd_dvrf = fmd->fmd_dvrf; vr_pkt_type(pkt, 0, &fmd_new); /* * XXX: for vcp ports, there won't be bridge table entries. to avoid * doing vr_bridge_input, we check for the flag NO_ARP_PROXY and * and if set, directly send out on that interface */ if (vif_is_vhost(vif) || (vif->vif_flags & VIF_FLAG_NO_ARP_PROXY)) { vif->vif_tx(vif, pkt, fmd); } else { vr_bridge_input(vif->vif_router, pkt, &fmd_new); } return; }
/* * vr_interface_input() is invoked if a packet ingresses an interface. * This function demultiplexes the packet to right input * function depending on the protocols enabled on the VIF */ unsigned int vr_virtual_input(unsigned short vrf, struct vr_interface *vif, struct vr_packet *pkt, unsigned short vlan_id) { struct vr_forwarding_md fmd; vr_init_forwarding_md(&fmd); fmd.fmd_vlan = vlan_id; fmd.fmd_dvrf = vrf; if (vif->vif_flags & VIF_FLAG_MIRROR_RX) { fmd.fmd_dvrf = vif->vif_vrf; vr_mirror(vif->vif_router, vif->vif_mirror_id, pkt, &fmd); } if (vr_pkt_type(pkt, 0, &fmd) < 0) { vif_drop_pkt(vif, pkt, 1); return 0; } /* * we really do not allow any broadcast packets from interfaces * that are part of transparent service chain, since transparent * service chain bridges packets across vrf (and hence loops can * happen) */ if ((pkt->vp_flags & VP_FLAG_MULTICAST) && (vif_is_service(vif))) { vif_drop_pkt(vif, pkt, 1); return 0; } if (!vr_flow_forward(pkt->vp_if->vif_router, pkt, &fmd)) return 0; vr_bridge_input(vif->vif_router, pkt, &fmd); return 0; }
unsigned int vr_l2_input(unsigned short vrf, struct vr_packet *pkt, struct vr_forwarding_md *fmd) { return vr_bridge_input(pkt->vp_if->vif_router, vrf, pkt, fmd); }