unsigned int vr_fabric_input(struct vr_interface *vif, struct vr_packet *pkt, unsigned short vlan_id) { int handled = 0; unsigned short pull_len; struct vr_forwarding_md fmd; vr_init_forwarding_md(&fmd); fmd.fmd_vlan = vlan_id; fmd.fmd_dvrf = vif->vif_vrf; if (vr_pkt_type(pkt, 0, &fmd) < 0) { vif_drop_pkt(vif, pkt, 1); return 0; } if (pkt->vp_type == VP_TYPE_IP6) return vif_xconnect(vif, pkt, &fmd); pull_len = pkt_get_network_header_off(pkt) - pkt_head_space(pkt); pkt_pull(pkt, pull_len); if (pkt->vp_type == VP_TYPE_IP || pkt->vp_type == VP_TYPE_IP6) handled = vr_l3_input(pkt, &fmd); else if (pkt->vp_type == VP_TYPE_ARP) handled = vr_arp_input(pkt, &fmd); if (!handled) { pkt_push(pkt, pull_len); return vif_xconnect(vif, pkt, &fmd); } return 0; }
/* * arp responses from vhostX need to be cross connected. nothing * needs to be done for arp responses from VMs, while responses * from fabric needs to be Xconnected and sent to agent */ static int vr_handle_arp_reply(struct vr_arp *sarp, struct vr_packet *pkt, struct vr_forwarding_md *fmd) { struct vr_interface *vif = pkt->vp_if; struct vr_packet *cloned_pkt; if (vif_mode_xconnect(vif) || vif->vif_type == VIF_TYPE_HOST) return vif_xconnect(vif, pkt, fmd); if (vif->vif_type != VIF_TYPE_PHYSICAL) { if (vif_is_virtual(vif)) { vr_preset(pkt); return vr_trap(pkt, fmd->fmd_dvrf, AGENT_TRAP_ARP, NULL); } vr_pfree(pkt, VP_DROP_INVALID_IF); return 0; } cloned_pkt = vr_pclone(pkt); if (cloned_pkt) { vr_preset(cloned_pkt); vif_xconnect(vif, cloned_pkt, fmd); } return vr_trap(pkt, fmd->fmd_dvrf, AGENT_TRAP_ARP, NULL); }
static int vr_handle_arp_request(struct vr_arp *sarp, struct vr_packet *pkt, struct vr_forwarding_md *fmd) { bool handled = true; unsigned char dmac[VR_ETHER_ALEN]; mac_response_t arp_result; struct vr_packet *pkt_c; struct vr_interface *vif = pkt->vp_if; arp_result = vif->vif_mac_request(vif, pkt, fmd, dmac); switch (arp_result) { case MR_PROXY: vr_arp_proxy(sarp, pkt, fmd, dmac); break; case MR_XCONNECT: vif_xconnect(pkt->vp_if, pkt, fmd); break; case MR_TRAP_X: pkt_c = vr_pclone(pkt); if (pkt_c) vif_xconnect(pkt->vp_if, pkt_c, fmd); vr_trap(pkt, fmd->fmd_dvrf, AGENT_TRAP_ARP, NULL); break; case MR_TRAP: vr_trap(pkt, fmd->fmd_dvrf, AGENT_TRAP_ARP, NULL); break; case MR_DROP: vr_pfree(pkt, VP_DROP_INVALID_ARP); break; case MR_FLOOD: default: handled = false; break; } return handled; }
/* * arp responses from vhostX need to be cross connected. nothing * needs to be done for arp responses from VMs, while responses * from fabric needs to be Xconnected and sent to agent */ static int vr_handle_arp_reply(struct vrouter *router, unsigned short vrf, struct vr_arp *sarp, struct vr_packet *pkt) { struct vr_interface *vif = pkt->vp_if; struct vr_packet *cloned_pkt; if (vif_mode_xconnect(vif) || vif->vif_type == VIF_TYPE_HOST) return vif_xconnect(vif, pkt); if (vif->vif_type != VIF_TYPE_PHYSICAL) { vr_pfree(pkt, VP_DROP_INVALID_IF); return 0; } cloned_pkt = vr_pclone(pkt); if (cloned_pkt) { vr_preset(cloned_pkt); vif_xconnect(vif, cloned_pkt); } return vr_trap(pkt, vrf, AGENT_TRAP_ARP, NULL); }
/* vhost driver */ static int vhost_rx(struct vr_interface *vif, struct vr_packet *pkt, unsigned short vlan_id __attribute__((unused))) { struct vr_interface_stats *stats = vif_get_stats(vif, pkt->vp_cpu); stats->vis_ibytes += pkt_len(pkt); stats->vis_ipackets++; /* please see the text on xconnect mode */ if (vif_mode_xconnect(vif)) return vif_xconnect(vif, pkt); return vr_input(vif->vif_vrf, vif, pkt); }
static int vr_handle_arp_request(struct vrouter *router, unsigned short vrf, struct vr_arp *sarp, struct vr_packet *pkt) { struct vr_packet *cloned_pkt; struct vr_interface *vif = pkt->vp_if; unsigned short proto = htons(VR_ETH_PROTO_ARP); struct vr_eth *eth; struct vr_arp *arp; unsigned int dpa; bool should_proxy = false; /* * still @ l2 level, and hence we can use the mode of the interface * to figure out whether we need to xconnect or not. in the xconnect * mode, just pass it to the peer so that he can handle the arp requests */ if (vif_mode_xconnect(vif)) return vif_xconnect(vif, pkt); should_proxy = vr_should_proxy(vif, sarp->arp_dpa, sarp->arp_spa); /* * if vr should not proxy, all the other arp requests should go out on * the physical interface */ if (vif->vif_type == VIF_TYPE_HOST && !should_proxy) return vif_xconnect(vif, pkt); /* * grat arp from * * VMs - need to be dropped * Fabric - need to be xconnected and also sent to agent * Vhost - xconnected above */ if (vr_grat_arp(sarp)) { if (vif->vif_type == VIF_TYPE_VIRTUAL) { vr_pfree(pkt, VP_DROP_GARP_FROM_VM); return 0; } cloned_pkt = vr_pclone(pkt); if (cloned_pkt) { vr_preset(cloned_pkt); vif_xconnect(vif, cloned_pkt); } return vr_trap(pkt, vrf, AGENT_TRAP_ARP, NULL); } if (should_proxy) { pkt_reset(pkt); eth = (struct vr_eth *)pkt_data(pkt); memcpy(eth->eth_dmac, sarp->arp_sha, VR_ETHER_ALEN); memcpy(eth->eth_smac, vif->vif_mac, VR_ETHER_ALEN); memcpy(ð->eth_proto, &proto, sizeof(proto)); arp = (struct vr_arp *)pkt_pull_tail(pkt, VR_ETHER_HLEN); sarp->arp_op = htons(VR_ARP_OP_REPLY); memcpy(sarp->arp_sha, vif->vif_mac, VR_ETHER_ALEN); memcpy(sarp->arp_dha, eth->eth_dmac, VR_ETHER_ALEN); dpa = sarp->arp_dpa; memcpy(&sarp->arp_dpa, &sarp->arp_spa, sizeof(sarp->arp_dpa)); memcpy(&sarp->arp_spa, &dpa, sizeof(sarp->arp_spa)); memcpy(arp, sarp, sizeof(*sarp)); pkt_pull_tail(pkt, sizeof(*arp)); vif->vif_tx(vif, pkt); } else { /* requests for which vr doesn't have to do anything */ vr_pfree(pkt, VP_DROP_INVALID_ARP); } return 0; }