static int eth_tx(struct vr_interface *vif, struct vr_packet *pkt) { int ret; struct vr_forwarding_md fmd; struct vr_interface_stats *stats = vif_get_stats(vif, pkt->vp_cpu); /* * GRO packets come here twice - once with VP_FLAG_GRO set and * once without the flag set. Don't count them twice. */ if (((pkt->vp_flags & VP_FLAG_GRO) == 0) || (vif->vif_type != VIF_TYPE_VIRTUAL)) { stats->vis_obytes += pkt_len(pkt); stats->vis_opackets++; } if (vif->vif_flags & VIF_FLAG_MIRROR_TX) { vr_init_forwarding_md(&fmd); fmd.fmd_dvrf = vif->vif_vrf; vr_mirror(vif->vif_router, vif->vif_mirror_id, pkt, &fmd); } ret = hif_ops->hif_tx(vif, pkt); if (ret != 0) { ret = 0; stats->vis_oerrors++; } return ret; }
void vr_dpdk_packet_wakeup(struct vr_interface *vif) { struct vr_interface_stats *stats; struct vrouter *router; if (unlikely(vif == NULL)) { /* get global agent vif */ router = vrouter_get(0); vif = router->vr_agent_if; } if (likely(vr_dpdk.packet_event_sock != NULL)) { if (likely(vif != NULL)) { stats = vif_get_stats(vif, rte_lcore_id()); stats->vis_port_osyscalls++; } else { /* no agent interface - no counter */ } if (vr_usocket_eventfd_write(vr_dpdk.packet_event_sock) < 0) { vr_usocket_close(vr_dpdk.packet_event_sock); vr_dpdk.packet_event_sock = NULL; } } }
static int agent_rx(struct vr_interface *vif, struct vr_packet *pkt, unsigned short vlan_id __attribute__((unused))) { struct agent_hdr *hdr; struct vr_interface *agent_vif; struct vr_interface_stats *stats = vif_get_stats(vif, pkt->vp_cpu); stats->vis_ibytes += pkt_len(pkt); stats->vis_ipackets++; hdr = (struct agent_hdr *)pkt_pull(pkt, sizeof(struct vr_eth)); if (!hdr || !pkt_pull(pkt, sizeof(*hdr))) { stats->vis_ierrors++; vr_pfree(pkt, VP_DROP_PULL); return 0; } /* * Update the original (OS visible) packet to point to the * l2 header of the injected packet */ vr_pset_data(pkt, pkt->vp_data); if (ntohs(hdr->hdr_cmd) & AGENT_CMD_ROUTE) { /* * XXX * Packet with command "route" from agent may * result in flow setup, this breaks the * assumption that all packets for a flow will * reach same CPU. Need a better way to handle this */ agent_vif = __vrouter_get_interface(vrouter_get(0), ntohs(hdr->hdr_ifindex)); if (!agent_vif) { agent_vif = vif; } pkt->vp_if = agent_vif; vr_interface_input(ntohs(hdr->hdr_vrf), agent_vif, pkt, VLAN_ID_INVALID); } else { vif = __vrouter_get_interface(vrouter_get(0), ntohs(hdr->hdr_ifindex)); if (!vif) { stats->vis_ierrors++; vr_pfree(pkt, VP_DROP_INVALID_IF); return 0; } pkt->vp_type = VP_TYPE_AGENT; pkt_set_network_header(pkt, pkt->vp_data + sizeof(struct vr_eth)); pkt_set_inner_network_header(pkt, pkt->vp_data + sizeof(struct vr_eth)); return vif->vif_tx(vif, pkt); } return 0; }
void vif_drop_pkt(struct vr_interface *vif, struct vr_packet *pkt, bool input) { struct vr_interface_stats *stats = vif_get_stats(vif, pkt->vp_cpu); if (input) stats->vis_ierrors++; else stats->vis_oerrors++; vr_pfree(pkt, VP_DROP_INTERFACE_DROP); return; }
/* 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); }
/* eth driver */ static int eth_srx(struct vr_interface *vif, struct vr_packet *pkt, unsigned short vlan_id) { unsigned short vrf; struct vr_interface_stats *stats = vif_get_stats(vif, pkt->vp_cpu); stats->vis_ibytes += pkt_len(pkt); stats->vis_ipackets++; if (vlan_id >= VIF_VRF_TABLE_ENTRIES) vrf = vif->vif_vrf; else vrf = vif->vif_vrf_table[vlan_id]; return vr_input(vrf, vif, pkt); }
static int agent_tx(struct vr_interface *vif, struct vr_packet *pkt) { int ret; struct vr_interface_stats *stats = vif_get_stats(vif, pkt->vp_cpu); stats->vis_obytes += pkt_len(pkt); stats->vis_opackets++; ret = hif_ops->hif_tx(vif, pkt); if (ret != 0) { ret = 0; stats->vis_oerrors++; } return ret; }
static int vhost_tx(struct vr_interface *vif, struct vr_packet *pkt) { int ret; struct vr_interface_stats *stats = vif_get_stats(vif, pkt->vp_cpu); stats->vis_obytes += pkt_len(pkt); stats->vis_opackets++; if (vif->vif_type == VIF_TYPE_XEN_LL_HOST) memcpy(pkt_data(pkt), vif->vif_mac, sizeof(vif->vif_mac)); ret = hif_ops->hif_rx(vif, pkt); if (ret < 0) { ret = 0; stats->vis_oerrors++; } return ret; }
static void vr_dpdk_packet_receive(struct vr_usocket *usockp) { const unsigned lcore_id = rte_lcore_id(); struct vr_dpdk_lcore *lcore = vr_dpdk.lcores[lcore_id]; struct vr_interface_stats *stats; RTE_LOG(DEBUG, USOCK, "%s[%lx]: FD %d\n", __func__, pthread_self(), usockp->usock_fd); /** * Packets is read from the agent's socket here. On success, a counter for * packets dequeued from the interface is incremented. */ stats = vif_get_stats(usockp->usock_vif, lcore_id); if (usockp->usock_vif) { stats->vis_port_ipackets++; /* buf_addr and data_off do not change */ usockp->usock_mbuf->data_len = usockp->usock_read_len; usockp->usock_mbuf->pkt_len = usockp->usock_read_len; /* convert mbuf to vr_packet */ vr_dpdk_packet_get(usockp->usock_mbuf, usockp->usock_vif); /* send the mbuf to vRouter */ vr_dpdk_lcore_vroute(lcore, usockp->usock_vif, &usockp->usock_mbuf, 1); /* flush packet TX queues immediately */ vr_dpdk_lcore_flush(lcore); } else { /** * If reading from socket failed, increment counter for interface * dequeue drops. */ RTE_LOG(ERR, VROUTER, "Error receiving from packet socket: no vif attached\n"); vr_dpdk_pfree(usockp->usock_mbuf, VP_DROP_INTERFACE_DROP); stats->vis_port_ierrors++; } usockp->usock_mbuf = NULL; usockp->usock_rx_buf = NULL; usockp->usock_buf_len = 0; return; }
static int eth_rx(struct vr_interface *vif, struct vr_packet *pkt, unsigned short vlan_id) { 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 * * since we would like the packets to reach the VMs (if they were * destined to in the first place), packets have to traverse the * stack. so, just mark a flag suggesting that packet is destined * for the vrouter and force the vrouter to receive the packet */ if (vif_mode_xconnect(vif)) pkt->vp_flags |= VP_FLAG_TO_ME; return vr_interface_input(vif->vif_vrf, vif, pkt, vlan_id); }
static void vr_dpdk_packet_ring_drain(struct vr_usocket *usockp) { int i; unsigned nb_pkts; struct rte_mbuf *mbuf_arr[VR_DPDK_RX_BURST_SZ]; const unsigned lcore_id = rte_lcore_id(); struct vr_interface_stats *stats; RTE_LOG(DEBUG, USOCK, "%s[%lx]: draining packet ring...\n", __func__, pthread_self()); if (unlikely(usockp->usock_parent->usock_vif == NULL)) return; rcu_thread_offline(); stats = vif_get_stats(usockp->usock_parent->usock_vif, lcore_id); do { nb_pkts = rte_ring_sc_dequeue_burst(vr_dpdk.packet_ring, (void **)&mbuf_arr, VR_DPDK_RX_BURST_SZ); for (i = 0; i < nb_pkts; i++) { if (usock_mbuf_write(usockp->usock_parent, mbuf_arr[i]) >= 0) stats->vis_port_opackets++; else { stats->vis_port_oerrors++; RTE_LOG(DEBUG, USOCK, "%s: Error writing mbuf to packet socket: %s (%d)\n", __func__, rte_strerror(errno), errno); } rte_pktmbuf_free(mbuf_arr[i]); } } while (nb_pkts > 0); rcu_thread_online(); }
static int agent_send(struct vr_interface *vif, struct vr_packet *pkt, void *ifspecific) { int len; struct agent_hdr *hdr; unsigned char *rewrite; struct vr_interface_stats *stats = vif_get_stats(vif, pkt->vp_cpu); struct vr_packet *pkt_c; struct agent_send_params *params = (struct agent_send_params *)ifspecific; vr_preset(pkt); if (pkt_head_space(pkt) < AGENT_PKT_HEAD_SPACE) { len = pkt_len(pkt); if (agent_trap_may_truncate(params->trap_reason)) { len = MINIMUM(len, VR_AGENT_MIN_PACKET_LEN); } pkt_c = pkt_copy(pkt, 0, len); if (pkt_c) { vr_pfree(pkt, VP_DROP_DUPLICATED); pkt = pkt_c; } } hdr = (struct agent_hdr *)pkt_push(pkt, sizeof(struct agent_hdr)); if (!hdr) goto drop; hdr->hdr_ifindex = htons(pkt->vp_if->vif_idx); hdr->hdr_vrf = htons(params->trap_vrf); hdr->hdr_cmd = htons(params->trap_reason); switch (params->trap_reason) { case AGENT_TRAP_FLOW_MISS: case AGENT_TRAP_ECMP_RESOLVE: case AGENT_TRAP_SOURCE_MISMATCH: if (params->trap_param) hdr->hdr_cmd_param = htonl(*(unsigned int *)(params->trap_param)); break; case AGENT_TRAP_DIAG: if (params->trap_param) hdr->hdr_cmd_param = htonl(*(unsigned int *)(params->trap_param)); break; default: hdr->hdr_cmd_param = 0; break; } rewrite = pkt_push(pkt, VR_ETHER_HLEN); if (!rewrite) goto drop; memcpy(rewrite, vif->vif_rewrite, VR_ETHER_HLEN); return vif->vif_tx(vif, pkt); drop: stats->vis_oerrors++; vr_pfree(pkt, VP_DROP_PUSH); return 0; }