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