Line data Source code
1 : /* 2 : * vr_dpdk_packet.c -- the packet interface 3 : * 4 : * Copyright (c) 2014, Juniper Networks, Inc. 5 : * All rights reserved 6 : */ 7 : 8 : #include "vr_dpdk.h" 9 : #include "vr_queue.h" 10 : #include "vr_dpdk_usocket.h" 11 : 12 : #include <stdio.h> 13 : #include <unistd.h> 14 : #include <stdbool.h> 15 : 16 : int dpdk_packet_core_id = -1; 17 : 18 : void 19 483 : vr_dpdk_packet_wakeup(struct vr_interface *vif) 20 : { 21 : struct vr_interface_stats *stats; 22 : struct vrouter *router; 23 : 24 483 : if (unlikely(vif == NULL)) { 25 : /* get global agent vif */ 26 483 : router = vrouter_get(0); 27 483 : vif = router->vr_agent_if; 28 : } 29 : 30 483 : if (likely(vr_dpdk.packet_event_sock != NULL)) { 31 0 : if (likely(vif != NULL)) { 32 0 : stats = vif_get_stats(vif, rte_lcore_id()); 33 0 : stats->vis_port_osyscalls++; 34 : } else { 35 : /* no agent interface - no counter */ 36 : } 37 0 : if (vr_usocket_eventfd_write(vr_dpdk.packet_event_sock) < 0) { 38 0 : vr_usocket_close(vr_dpdk.packet_event_sock); 39 0 : vr_dpdk.packet_event_sock = NULL; 40 : } 41 : } 42 483 : } 43 : 44 : /* RCU callback called on packet lcore */ 45 : void 46 0 : vr_dpdk_packet_rcu_cb(struct rcu_head *rh) 47 : { 48 : struct vr_dpdk_rcu_cb_data *cb_data; 49 : 50 0 : cb_data = CONTAINER_OF(rcd_rcu, struct vr_dpdk_rcu_cb_data, rh); 51 : 52 : /* Call the user call back */ 53 0 : cb_data->rcd_user_cb(cb_data->rcd_router, cb_data->rcd_user_data); 54 0 : vr_free(cb_data, VR_DEFER_OBJECT); 55 0 : } 56 : 57 : int 58 53 : dpdk_packet_io(void) 59 : { 60 : int ret; 61 53 : struct vr_dpdk_lcore *lcore = vr_dpdk.lcores[rte_lcore_id()]; 62 : 63 53 : wait_for_connection: 64 : RTE_LOG_DP(DEBUG, VROUTER, "%s[%lx]: waiting for packet transport\n", 65 : __func__, pthread_self()); 66 : 67 : /* Set the thread offline while busy waiting for the 68 : * transport socket to apperar. 69 : */ 70 53 : rcu_thread_offline(); 71 9715949 : while (!vr_dpdk.packet_transport) { 72 : /* handle an IPC command */ 73 9715949 : if (unlikely(vr_dpdk_lcore_cmd_handle(lcore))) 74 53 : return -1; 75 9715896 : usleep(VR_DPDK_SLEEP_SERVICE_US); 76 : } 77 0 : rcu_thread_online(); 78 : 79 : RTE_LOG_DP(DEBUG, VROUTER, "%s[%lx]: FD %d\n", __func__, pthread_self(), 80 : ((struct vr_usocket *)vr_dpdk.packet_transport)->usock_fd); 81 0 : ret = vr_usocket_io(vr_dpdk.packet_transport); 82 0 : if (ret < 0) { 83 0 : vr_dpdk.packet_transport = NULL; 84 : /* handle an IPC command */ 85 0 : if (unlikely(vr_dpdk_lcore_cmd_handle(lcore))) 86 0 : return -1; 87 0 : usleep(VR_DPDK_SLEEP_SERVICE_US); 88 0 : goto wait_for_connection; 89 : } 90 : 91 0 : return ret; 92 : } 93 : 94 : void 95 42 : dpdk_packet_socket_close(void) 96 : { 97 42 : if (!vr_dpdk.packet_transport) 98 42 : return; 99 : 100 : /* close and free up the memory both for packet usock and binded event usock */ 101 0 : vr_usocket_close(vr_dpdk.packet_transport); 102 0 : vr_dpdk_packet_wakeup(NULL); 103 0 : vr_dpdk.packet_transport = NULL; 104 0 : vr_dpdk.packet_event_sock = NULL; 105 : 106 0 : return; 107 : } 108 : 109 : int 110 0 : dpdk_packet_socket_init(void) 111 : { 112 0 : void *event_sock = NULL; 113 : int err; 114 : void *packet_transport; 115 : 116 0 : packet_transport = (void *)vr_usocket(PACKET, RAW); 117 0 : if (!packet_transport) 118 0 : return -1; 119 : 120 0 : if (!vr_dpdk.packet_ring) { 121 0 : vr_dpdk.packet_ring = rte_ring_lookup("packet_tx"); 122 0 : if (!vr_dpdk.packet_ring) { 123 : /* multi-producers single-consumer ring */ 124 0 : vr_dpdk.packet_ring = rte_ring_create("packet_tx", vr_dpdk_tx_ring_sz, 125 : SOCKET_ID_ANY, RING_F_SC_DEQ); 126 0 : if (!vr_dpdk.packet_ring) { 127 0 : RTE_LOG(ERR, VROUTER, " error creating packet ring\n"); 128 0 : goto error; 129 : } 130 : } 131 : } 132 : 133 : /* create and bind event usock to wake up the packet lcore */ 134 0 : event_sock = (void *)vr_usocket(EVENT, RAW); 135 0 : if (!event_sock) { 136 0 : RTE_LOG(ERR, VROUTER, " error creating packet event\n"); 137 0 : goto error; 138 : } 139 : 140 0 : if (vr_usocket_bind_usockets(packet_transport, 141 : event_sock)) { 142 0 : RTE_LOG(ERR, VROUTER, " error binding packet event\n"); 143 0 : goto error; 144 : } 145 0 : vr_dpdk.packet_event_sock = event_sock; 146 0 : vr_dpdk.packet_transport = packet_transport; 147 : 148 0 : return 0; 149 : 150 0 : error: 151 0 : err = errno; 152 0 : if (event_sock) 153 0 : vr_usocket_close(event_sock); 154 0 : vr_usocket_close(packet_transport); 155 0 : vr_dpdk.packet_transport = NULL; 156 0 : errno = err; 157 : 158 0 : return -ENOMEM; 159 : }