/* * Initialize a pool of keys * These are unique tokens that can be obtained by threads * calling lthread_key_create() */ void _lthread_key_pool_init(void) { static struct rte_ring *pool; struct lthread_key *new_key; char name[MAX_LTHREAD_NAME_SIZE]; bzero(key_table, sizeof(key_table)); /* only one lcore should do this */ if (rte_atomic64_cmpset(&key_pool_init, 0, 1)) { snprintf(name, MAX_LTHREAD_NAME_SIZE, "lthread_key_pool_%d", getpid()); pool = rte_ring_create(name, LTHREAD_MAX_KEYS, 0, 0); LTHREAD_ASSERT(pool); int i; for (i = 1; i < LTHREAD_MAX_KEYS; i++) { new_key = &key_table[i]; rte_ring_mp_enqueue((struct rte_ring *)pool, (void *)new_key); } key_pool = pool; } /* other lcores wait here till done */ while (key_pool == NULL) { rte_compiler_barrier(); sched_yield(); }; }
/* * Enqueue single packet to a port */ static void send_to_port(uint8_t vportid, struct rte_mbuf *buf) { struct port_queue *pq = &port_queues[vportid & PORT_MASK]; if (rte_ring_mp_enqueue(pq->tx_q, (void *)buf) < 0) { rte_pktmbuf_free(buf); } }
/* * Delete a key */ int lthread_key_delete(unsigned int k) { struct lthread_key *key; key = (struct lthread_key *) &key_table[k]; if (k > LTHREAD_MAX_KEYS) return POSIX_ERRNO(EINVAL); key->destructor = NULL; rte_ring_mp_enqueue((struct rte_ring *)key_pool, (void *)key); return 0; }
/* * Function sends unmatched packets to vswitchd. */ void send_packet_to_vswitchd(struct rte_mbuf *mbuf, struct dpdk_upcall *info) { int rslt = 0; void *mbuf_ptr = NULL; const uint64_t dpif_send_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S * DPIF_SEND_US; uint64_t cur_tsc = 0; uint64_t diff_tsc = 0; static uint64_t prev_tsc = 0; /* send one packet, delete information about segments */ rte_pktmbuf_pkt_len(mbuf) = rte_pktmbuf_data_len(mbuf); /* allocate space before the packet for the upcall info */ mbuf_ptr = rte_pktmbuf_prepend(mbuf, sizeof(*info)); if (mbuf_ptr == NULL) { printf("Cannot prepend upcall info\n"); rte_pktmbuf_free(mbuf); stats_vswitch_tx_drop_increment(INC_BY_1); stats_vport_tx_drop_increment(VSWITCHD, INC_BY_1); return; } rte_memcpy(mbuf_ptr, info, sizeof(*info)); /* send the packet and the upcall info to the daemon */ rslt = rte_ring_mp_enqueue(vswitchd_packet_ring, mbuf); if (rslt < 0) { if (rslt == -ENOBUFS) { rte_pktmbuf_free(mbuf); stats_vswitch_tx_drop_increment(INC_BY_1); stats_vport_tx_drop_increment(VSWITCHD, INC_BY_1); return; } else { stats_vport_overrun_increment(VSWITCHD, INC_BY_1); } } stats_vport_tx_increment(VSWITCHD, INC_BY_1); cur_tsc = rte_rdtsc(); diff_tsc = cur_tsc - prev_tsc; prev_tsc = cur_tsc; /* Only signal the daemon after 100 milliseconds */ if (unlikely(diff_tsc > dpif_send_tsc)) send_signal_to_dpif(); }
int sched_module_action(struct rte_mbuf*pktbuf,struct sched_stat_str*lpstat) { int rc; #if 0 if(lpstat->iFlowIdx==-1) return -1; #endif if(lpstat->iDiscard==TRUE) return -1; switch(lpstat->tc_color) { case TC_GREEN://enqueue pkt into queue with higher priority rc=EnqueueIntoPortByQueueID(lpstat->iport_out,0,pktbuf); if(!rc) lpstat->iDiscard=TRUE; break; case TC_YELLOW://enqueue pkt into queue with less priority rc=EnqueueIntoPortByQueueID(lpstat->iport_out,(gPortParaConf[lpstat->iport_out].inb_tx_ring>=2)?1:0,pktbuf); if(!rc) lpstat->iDiscard=TRUE; break; case TC_RED: switch(lpstat->iPhaze) { case PHAZE_PRIMARY://re-enqueue into secondary sched queue rc=rte_ring_mp_enqueue(sched_mod_list[lpstat->isched_mod_id].rrSecLev,pktbuf); if(rc==-ENOBUFS) lpstat->iDiscard=TRUE; break; case PHAZE_SECONDARY://discard re-metred and red-colored pkts lpstat->iDiscard=TRUE; break; default://may this case will never occur lpstat->iDiscard=TRUE; break; } break; case TC_UNDEF: lpstat->iDiscard=TRUE; break; } return 0; }
/* * Send a reply message to the vswitchd */ static void send_reply_to_vswitchd(struct dpdk_message *reply) { struct rte_mbuf *mbuf = NULL; void *pktmbuf_data = NULL; int rslt = 0; /* Preparing the buffer to send */ mbuf = rte_pktmbuf_alloc(pktmbuf_pool); if (!mbuf) { RTE_LOG(WARNING, APP, "Error : Unable to allocate an mbuf " ": %s : %d", __FUNCTION__, __LINE__); stats_vswitch_tx_drop_increment(INC_BY_1); stats_vport_rx_drop_increment(VSWITCHD, INC_BY_1); return; } pktmbuf_data = rte_pktmbuf_mtod(mbuf, void *); rte_memcpy(pktmbuf_data, reply, sizeof(*reply)); rte_pktmbuf_data_len(mbuf) = sizeof(*reply); /* Sending the buffer to vswitchd */ rslt = rte_ring_mp_enqueue(vswitchd_reply_ring, (void *)mbuf); if (rslt < 0) { if (rslt == -ENOBUFS) { rte_pktmbuf_free(mbuf); stats_vswitch_tx_drop_increment(INC_BY_1); stats_vport_rx_drop_increment(VSWITCHD, INC_BY_1); } else { stats_vport_overrun_increment(VSWITCHD, INC_BY_1); stats_vport_rx_increment(VSWITCHD, INC_BY_1); } } else { stats_vport_rx_increment(VSWITCHD, INC_BY_1); } }
int app_func(void *arg) { struct rte_ring *ring1, *ring2; static struct message *msg1, *msg2; static struct message *msg3, *msg4; static struct message out_msg1, out_msg2; unsigned long long int t1 = 0, t2 = 0; int i = 0; out_msg1.message_id = 2; out_msg1.payload1 = 0; out_msg2.message_id = 2; out_msg2.payload1 = 0; #ifndef __baremetal__ cpu_set_t cpuset; CPU_ZERO(&cpuset); CPU_SET(1, &cpuset); pthread_t current_thread = pthread_self(); pthread_setaffinity_np(current_thread, sizeof(cpu_set_t), &cpuset); #endif if (*(int*)arg == 0) { ring1 = app1; ring2 = app2; // Only this branch is used for now, for 3 threads } else { ring1 = app3; ring2 = app3; } // Simple round robin message parser/scheduler for (i = 0; i < N; i++) { int received1 = 0, received2 = 0; int received3 = 0, received4 = 0; // Scan the command queue, barrier while (!(received1 && received2 && received3 && received4)) { /*#ifdef DEBUG #ifdef __baremetal__ kprintf #else printf #endif ("app spin %d %d %d %d\n", received1, received2, received3, received4); #endif*/ if(!received1) { if(!rte_ring_mc_dequeue(ring1, (void **)&msg1)) { #ifdef DEBUG #ifdef __baremetal__ kprintf #else printf #endif ("packet from io ring 1 %d %d\n", msg1->message_id, msg1->payload1); #endif received1 = -1; } } if(!received2) { if(!rte_ring_mc_dequeue(ring2, (void **)&msg2)) { received2 = -1; #ifdef DEBUG #ifdef __baremetal__ kprintf #else printf #endif ("packet from io ring 2 %d %d\n", msg2->message_id, msg2->payload1); #endif } } if(!received3) { if(!rte_ring_mc_dequeue(ring1, (void **)&msg3)) { received3 = -1; #ifdef DEBUG #ifdef __baremetal__ kprintf #else printf #endif ("packet from io ring 12 %d %d\n", msg3->message_id, msg3->payload1); #endif } } if(!received4) { if(!rte_ring_mc_dequeue(ring2, (void **)&msg4)) { received4 = -1; #ifdef DEBUG #ifdef __baremetal__ kprintf #else printf #endif ("packet from io ring 22 %d %d\n", msg4->message_id, msg4->payload1); #endif } } } if (t1 == 0) t1 = getticks(); else { #ifdef DEBUG #ifdef __baremetal__ kprintf #else printf #endif ("next iteration %d\n", (unsigned int)(getticks() - t1)); #endif } // Send stuff back, use mp function in case out_msg1.payload1++; int sent = rte_ring_mp_enqueue(out1, &out_msg1); out_msg2.payload1++; sent = rte_ring_mp_enqueue(out2, &out_msg2); } t2 = getticks(); #ifndef __baremetal__ printf #else kprintf #endif ("%d\n", ((unsigned int)(t2 - t1))/N); #ifndef __baremetal__ return 0; #else return ((unsigned int)(t2 - t1))/N; #endif }
// 2 pinned comms threads, processing 2out and 4in buffers. int io_func(void *arg) { struct rte_ring *ring1, *ring2; static struct message *out_msg1, *out_msg2; static struct message msg1, msg2; #ifndef __baremetal__ cpu_set_t cpuset; CPU_ZERO(&cpuset); pthread_t current_thread = pthread_self(); #endif msg1.payload1 = 0; msg2.payload1 = 0; if (*(int*)arg == 0) { msg1.message_id = 1; ring1 = out1; #ifndef __baremetal__ CPU_SET(2, &cpuset); pthread_setaffinity_np(current_thread, sizeof(cpu_set_t), &cpuset); #endif } else { msg2.message_id = 3; ring1 = out2; #ifndef __baremetal__ CPU_SET(3, &cpuset); pthread_setaffinity_np(current_thread, sizeof(cpu_set_t), &cpuset); #endif } // Simple round robin message sender/receiver while (1) { int received1 = 0, received2 = 0; unsigned long long t1 = getticks(); // Try sending msg1.payload1++; int sent = rte_ring_mp_enqueue(app1, &msg1); if (-1 == sent) {// FIXME to handle the error } msg2.payload1++; sent = rte_ring_mp_enqueue(app2, &msg2); // receive output, barrier while (!received1) { /*#ifdef DEBUG #ifdef __baremetal__ kprintf #else printf #endif ("io spin %d %d \n", received1, received2); #endif*/ if(!received1) { if(!rte_ring_mc_dequeue(ring1, (void **)&out_msg1)) { #ifdef DEBUG #ifdef __baremetal__ kprintf #else printf #endif ("packet from app ring 1 %d %d\n", out_msg1->message_id, out_msg1->payload1); #endif if (out_msg1->payload1 == N) return 0; received1 = -1; } } } } return 0; }
/* functional description: packet forward(enqueue) module,we push packet into QoS queue or TX queue input mod: RX_MOD_FORWARD output mod: RX_MOD_DROP RX_MOD_IDLE module stack pos: as 1st action ,before drop module,and below any policy module */ dbg_local enum RX_MOD_INDEX rx_module_forward(dbg_local struct rte_mbuf*pktbuf,dbg_local enum RX_MOD_INDEX imodid) { dbg_local int iPortIn; dbg_local int iPortOut; dbg_local int iFlowIdx; dbg_local int iDstIdx; dbg_local int uiSIP; dbg_local int uiDIP; dbg_local int idx; dbg_local int rc; dbg_local int iUsed; dbg_local int iMod; dbg_local struct ether_hdr *eh; dbg_local struct ether_arp *ea; dbg_local struct iphdr *iph; dbg_local int iPortForwardFlag[MAX_PORT_NB]; dbg_local struct rte_mbuf*rmPortForwardMbuf[MAX_PORT_NB]; dbg_local enum RX_MOD_INDEX nextmodid=imodid; if(imodid!=RX_MOD_FORWARD) goto local_ret; //phaze 1,we filter packet with illegal l2 and l3 address,and drop it //printf("input port:%d\n",(int)pktbuf->pkt.in_port); eh=rte_pktmbuf_mtod(pktbuf,struct ether_hdr*); uiSIP=0xffffffff; switch(HTONS(eh->ether_type)) { case ETH_TYPE_ARP: ea=(struct ether_arp *)(sizeof(struct ether_hdr)+(char*)eh); uiSIP=HTONL(MAKEUINT32FROMUINT8ARR(ea->arp_spa)); uiDIP=HTONL(MAKEUINT32FROMUINT8ARR(ea->arp_tpa)); break; case ETH_TYPE_IP: iph=(struct iphdr *)(sizeof(struct ether_hdr)+(char*)eh); uiSIP=HTONL(iph->ip_src); uiDIP=HTONL(iph->ip_dst); break; default: goto exception_tag; break; } iFlowIdx=find_net_entry(uiSIP,TRUE); //pkt source legality checking if(iFlowIdx==-1) goto exception_tag; if(gFlow[iFlowIdx].b_mac_learned==FALSE) goto exception_tag; if(gFlow[iFlowIdx].b_flow_enabled==FALSE) goto exception_tag; if(gFlow[iFlowIdx].portid!=pktbuf->pkt.in_port) goto exception_tag; if(!IS_MAC_EQUAL(eh->s_addr.addr_bytes,gFlow[iFlowIdx].eaHostMAC.addr_bytes)) goto exception_tag; iDstIdx=find_net_entry(uiDIP,TRUE); /*printf("%02x,%02x,%02x,%02x,%02x,%02x,\n",eh->d_addr.addr_bytes[0] ,eh->d_addr.addr_bytes[1] ,eh->d_addr.addr_bytes[2] ,eh->d_addr.addr_bytes[3] ,eh->d_addr.addr_bytes[4] ,eh->d_addr.addr_bytes[5] );*/ if(IS_MAC_BROADCAST(eh->d_addr.addr_bytes)){//link broadcast iUsed=FALSE; for(idx=0;idx<gNBPort;idx++) if(port_brdcst_map[(int)pktbuf->pkt.in_port][idx]==TRUE){ iPortForwardFlag[idx]=1; if(iUsed==FALSE){ rmPortForwardMbuf[idx]=pktbuf; iUsed=TRUE; }else{ rmPortForwardMbuf[idx]=rte_pktmbuf_clone(pktbuf,gmempool); if(!rmPortForwardMbuf[idx]) iPortForwardFlag[idx]=0; } }else iPortForwardFlag[idx]=0; }else{//link uicast for(idx=0;idx<gNBPort;idx++) iPortForwardFlag[idx]=0; if(iDstIdx!=-1){ // printf(".......idstidx!=-1.%08x\n",gFlow[iDstIdx].uiInnerIP); if(gFlow[iDstIdx].b_mac_learned==FALSE) goto exception_tag; // printf("Heror1\n"); if(gFlow[iDstIdx].b_flow_enabled==FALSE) goto exception_tag; // printf("Heror2\n"); iPortForwardFlag[(int)gFlow[iDstIdx].portid]=1; rmPortForwardMbuf[(int)gFlow[iDstIdx].portid]=pktbuf; } else { // printf(".......idstidx==-1\n"); if(port_def_frd_map[(int)pktbuf->pkt.in_port]!=-1){ iPortForwardFlag[port_def_frd_map[(int)pktbuf->pkt.in_port]]=1; rmPortForwardMbuf[port_def_frd_map[(int)pktbuf->pkt.in_port]]=pktbuf; } else goto exception_tag; } } //mirror--pkt--cloning for(idx=0;idx<gNBPort;idx++) { if(!iPortForwardFlag[idx])continue; switch(port_policy_map[(int)pktbuf->pkt.in_port][idx]) { case PORT_POLICY_MAP_DIRECT: //printf("...direct:%d->%d\n",(int)pktbuf->pkt.in_port,idx); rc=EnqueueIntoPortQueue(idx,&rmPortForwardMbuf[idx],1); //printf("...rc:%d\n",rc); if(!rc) goto exception_tag; break; case PORT_POLICY_MAP_QOS: //high nibble:dst port //low nibble :src port iMod=sched_mod_map[(int)rmPortForwardMbuf[idx]->pkt.in_port][idx]; rmPortForwardMbuf[idx]->pkt.in_port=MAKEBYTE(idx,rmPortForwardMbuf[idx]->pkt.in_port); rc=rte_ring_mp_enqueue(sched_mod_list[iMod].rrFirLev,rmPortForwardMbuf[idx]); if(rc==-ENOBUFS){ goto exception_tag; } break; case PORT_POLICY_MAP_UNDEFINE: goto exception_tag; break; } } local_ret: return nextmodid; exception_tag: nextmodid=RX_MOD_DROP; goto local_ret; }