Date: Sun, 17 Oct 2010 20:43:31 GMT From: Alexandre Fiveg <afiveg@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 184838 for review Message-ID: <201010172043.o9HKhV62043651@skunkworks.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/@@184838?ac=10 Change 184838 by afiveg@cottonmouth on 2010/10/17 20:42:25 Significantly reduced hardware-dependent part of code. Most of the function are removed into hardware-independent ringmap.c. The hardware-dependent function are now responsible only for accessing registers (HEAD, TAIL) and receive buffers allocated as array in the generic driver. capt_object structure is extended: the new members: rx/tx_buffers for accessing memory regions allocated by generic driver for receive and transmit, hw_rx/tx_ring for accessing hardware registers like HEAD and TAIL. Currently supported controllers: Intel 8254x (driver if_lem). Unfortunately, because of broken 10GbE adapter I've received for GSoC the work on 10GbE is stopped. Affected files ... .. //depot/projects/soc2010/ringmap/current/sys/dev/e1000/if_lem.c#35 edit .. //depot/projects/soc2010/ringmap/current/sys/dev/e1000/ringmap_8254.c#35 edit .. //depot/projects/soc2010/ringmap/current/sys/dev/e1000/ringmap_8254.h#32 delete .. //depot/projects/soc2010/ringmap/current/sys/dev/e1000/ringmap_e1000.h#24 delete .. //depot/projects/soc2010/ringmap/current/sys/net/ringmap.c#49 edit .. //depot/projects/soc2010/ringmap/current/sys/net/ringmap.h#49 edit .. //depot/projects/soc2010/ringmap/current/sys/net/ringmap_kernel.h#19 edit .. //depot/projects/soc2010/ringmap/doc/slides/Makefile#1 add .. //depot/projects/soc2010/ringmap/doc/slides/ringmap_slides.tex#1 add .. //depot/projects/soc2010/ringmap/doc/slides/section/Background/Capturing.tex#1 add .. //depot/projects/soc2010/ringmap/doc/slides/section/Motivation/Goal.tex#1 add .. //depot/projects/soc2010/ringmap/doc/slides/section/Motivation/Problem.tex#1 add .. //depot/projects/soc2010/ringmap/doc/slides/section/Performance/Results.tex#1 add .. //depot/projects/soc2010/ringmap/doc/slides/section/Performance/Setup.tex#1 add .. //depot/projects/soc2010/ringmap/doc/slides/section/Solution/Generic2Ringmap.tex#1 add .. //depot/projects/soc2010/ringmap/doc/slides/section/Solution/Overview.tex#1 add .. //depot/projects/soc2010/ringmap/doc/slides/section/Solution/Ringmap.tex#1 add .. //depot/projects/soc2010/ringmap/doc/slides/section/Summary/AchievedGoals.tex#1 add .. //depot/projects/soc2010/ringmap/doc/slides/section/Summary/FutureWorks.tex#1 add .. //depot/projects/soc2010/ringmap/scripts/build_ringmap.sh#31 edit .. //depot/projects/soc2010/ringmap/scripts/set_ringmap.sh#32 edit .. //depot/projects/soc2010/ringmap/scripts/tailf_ringmap_msgs.sh#26 edit Differences ... ==== //depot/projects/soc2010/ringmap/current/sys/dev/e1000/if_lem.c#35 (text+ko) ==== @@ -270,7 +270,7 @@ extern struct ringmap * ringmap_attach(device_t, struct ringmap_functions *); extern int ringmap_detach (device_t); -extern struct ringmap_functions ringmap_8254_f; +extern struct ringmap_functions ringmap_8254_functions; #endif #ifdef DEVICE_POLLING @@ -670,7 +670,7 @@ device_get_nameunit(dev)); #ifdef RINGMAP - adapter->rm = ringmap_attach (dev, &ringmap_8254_f); + adapter->rm = ringmap_attach (dev, &ringmap_8254_functions); if (adapter->rm == NULL) { goto err_rx_struct; } @@ -3498,7 +3498,7 @@ } #ifdef RINGMAP - adapter->rm->funcs->delayed_isr(adapter); + co = adapter->rm->funcs->delayed_isr(adapter, adapter->rm); #endif while ((current_desc->status & E1000_RXD_STAT_DD) && @@ -3556,8 +3556,8 @@ #ifdef RINGMAP RINGMAP_LOCK(adapter->rm); - if (adapter->rm->open_cnt) - adapter->rm->funcs->delayed_isr_per_packet(adapter->dev, i); + if ((adapter->rm->open_cnt) && (co != NULL)) + adapter->rm->funcs->per_packet_iteration(co, i); RINGMAP_UNLOCK(adapter->rm); #endif @@ -3670,12 +3670,8 @@ #ifdef RINGMAP RINGMAP_LOCK(adapter->rm); - SLIST_FOREACH(co, &adapter->rm->object_list, objects) { - adapter->rm->funcs->sync_head(co); - if (RING_NOT_EMPTY(co->ring)){ + if ((co != NULL) && (RING_NOT_EMPTY(co->ring))) wakeup(co->ring); - } - } RINGMAP_UNLOCK(adapter->rm); #endif @@ -3685,7 +3681,7 @@ if (--i < 0) i = adapter->num_rx_desc - 1; - /* RINGMAP: Don't write RDT. We do it in sync_tail() */ + /* RINGMAP: Don't write RDT. We'll do it after user has read packet */ #ifndef RINGMAP E1000_WRITE_REG(&adapter->hw, E1000_RDT(0), i); #endif ==== //depot/projects/soc2010/ringmap/current/sys/dev/e1000/ringmap_8254.c#35 (text+ko) ==== @@ -17,249 +17,92 @@ #include "e1000_api.h" #include "if_lem.h" -#include "ringmap_8254.h" -int rm_8254_set_slot(struct capt_object *, unsigned int); -void rm_8254_interrupt(void *); -void rm_8254_delayed_interrupt(void *); -void rm_8254_delayed_interrupt_per_packet(void *, int); -int rm_8254_print_ring_pointers(struct adapter *); -void rm_8254_sync_tail(struct capt_object *); -void rm_8254_sync_head(struct capt_object *); -struct capt_object * rm_8254_find_next(struct adapter *); int rm_8254_set_queue(struct capt_object *, unsigned int); +unsigned int rm_8245_get_rdh(void *hw_ring); +unsigned int rm_8245_get_rdt(void *hw_ring); +void rm_8245_set_rdt(unsigned int val, void *hw_ring); +struct mbuf * rm_8254_get_mbuf(void *buffer_area, unsigned int num); +vm_offset_t rm_8254_get_packet(void *buffer_area, unsigned int num); +vm_offset_t rm8254_get_rx_desc(void * rx_desc_area, unsigned int num); + extern devclass_t em_devclass; -extern void ringmap_print_slot(struct ring *, unsigned int); -extern void print_capt_obj(struct capt_object *); -extern int ringmap_filter(struct capt_object *, int); -struct ringmap_functions ringmap_8254_f = { - rm_8254_interrupt, - rm_8254_delayed_interrupt, - rm_8254_delayed_interrupt_per_packet, - rm_8254_sync_tail, - rm_8254_sync_head, - rm_8254_set_slot, - rm_8254_set_queue, +struct ringmap_functions ringmap_8254_functions = { + .isr = NULL, + .delayed_isr = NULL, + .per_packet_iteration = NULL, + .get_head = rm_8245_get_rdh, + .get_tail = rm_8245_get_rdt, + .set_tail = rm_8245_set_rdt, + .get_mbuf = rm_8254_get_mbuf, + .get_packet = rm_8254_get_packet, + .set_queue = rm_8254_set_queue, + .pkt_filter = NULL, }; -/* - * Write the userrp into the RDT register - * 2. SYNC_TAIL: RDT = ring->userrp - */ -void -rm_8254_sync_tail(struct capt_object *co) +struct mbuf * +rm_8254_get_mbuf(void *buffer_area, unsigned int num) { - struct adapter *adapter = (struct adapter *)device_get_softc(co->rm->dev); + struct em_buffer *buf = (struct em_buffer *)buffer_area; + return (buf[num].m_head); +} - RINGMAP_HW_SYNC_TAIL(adapter, co->ring); -} -/* Set value from RDH to the ring->kernrp*/ -void -rm_8254_sync_head(struct capt_object *co) +vm_offset_t +rm_8254_get_packet(void *buffer_area, unsigned int num) { - struct adapter *adapter = (struct adapter *)device_get_softc(co->rm->dev); - - RINGMAP_HW_SYNC_HEAD(adapter, co->ring); + struct mbuf *mb = rm_8254_get_mbuf(buffer_area, num); + return ((vm_offset_t)mb->m_data); } -/* - * This should be called from ISR. Other interrupts are disallowed! - * It means the functions must be as small as possible - */ -void inline -rm_8254_interrupt(void *arg) +unsigned int +rm_8245_get_rdh(void *hw_ring) { - /* Do nothing ... */ - return; + return (E1000_READ_REG((struct e1000_hw *)hw_ring, E1000_RDH(0))); } -void -rm_8254_delayed_interrupt(void *context) +unsigned int +rm_8245_get_rdt(void *hw_ring) { - struct adapter *adapter = (struct adapter *)context; - struct capt_object *co = NULL; - struct timeval last_ts; - - RINGMAP_INTR(start); - - RINGMAP_LOCK(adapter->rm); - /* Do the next steps only if there is capturing process */ - if (adapter->rm->open_cnt > 0) { - getmicrotime(&last_ts); - rm_8254_sync_tail(rm_8254_find_next(adapter)); - - SLIST_FOREACH(co, &adapter->rm->object_list, objects) { - if (co->ring != NULL) { -#if (RINGMAP_INTR_DEB) - PRINT_RING_PTRS(co->ring); -#endif - co->ring->last_ts = last_ts; - ++co->ring->intr_num; - } - } - } - RINGMAP_UNLOCK(adapter->rm); - - RINGMAP_INTR(end); + return (E1000_READ_REG((struct e1000_hw *)hw_ring, E1000_RDT(0))); } -void -rm_8254_delayed_interrupt_per_packet(void *context, int slot_num) +void +rm_8245_set_rdt(unsigned int val, void *hw_ring) { - device_t dev = (device_t)context; - struct capt_object *co = NULL; - struct adapter *adapter = NULL; - struct ringmap *rm = NULL; - - adapter = (struct adapter *)device_get_softc(dev); - rm = adapter->rm; - - RINGMAP_INTR(start); - - SLIST_FOREACH(co, &rm->object_list, objects) { - if (co->ring != NULL) { - co->ring->slot[slot_num].is_ok = 1; - co->ring->slot[slot_num].intr_num = co->ring->intr_num; - - ringmap_filter(co, slot_num); - -#ifdef RINGMAP_TIMESTAMP - co->ring->slot[slot_num].ts = co->ring->last_ts; -#endif -#if (RINGMAP_INTR_DEB) - PRINT_SLOT((co->ring), (slot_num)); -#endif - } - } - - RINGMAP_INTR(end); + E1000_WRITE_REG((struct e1000_hw *)hw_ring, E1000_RDT(0), val); } -/* Returns the ring which TAIL pointer is mostly near to to the HEAD(RDH) */ -struct capt_object * -rm_8254_find_next(struct adapter *adapter) +int +rm_8254_set_queue(struct capt_object *co, unsigned int i) { - unsigned int rdh, rdt, dist, min_dist = SLOTS_NUMBER; - struct ringmap *rm = adapter->rm; - struct capt_object *co = NULL, *min_co = NULL; - - rdh = RINGMAP_HW_READ_HEAD(adapter); - - SLIST_FOREACH(co, &rm->object_list, objects) { - rdt = co->ring->userrp; - dist = R_DISTANCE(rdh, rdt); - if (dist <= min_dist) { - min_dist = dist; - min_co = co; - } - } - - return (min_co); -} - - -int -rm_8254_set_slot(struct capt_object *co, unsigned int slot_num) -{ device_t dev = NULL; struct adapter *adapter = NULL; - struct ring *ring = NULL; - -#if (__RINGMAP_DEB) - printf("[%s] Set slot: %d\n", __func__, slot_num); -#endif dev = co->rm->dev; adapter = (struct adapter *)device_get_softc(dev); - ring = co->ring; - - /* First check ALL pointers */ - if (co == NULL) { - RINGMAP_ERROR(Pointer to capturing object is NULL); - goto fail; - } - if (co->rm == NULL) { - RINGMAP_ERROR(Pointer to ringmap is NULL); - goto fail; - } - if (GET_MBUF_P(adapter, slot_num) == NULL){ - RINGMAP_ERROR(Pointer to mbuf is NULL); - goto fail; - } - if (GET_PACKET_P(adapter, slot_num) == NULL){ - RINGMAP_ERROR(Pointer to packet is NULL); - goto fail; - } - if (GET_DESCRIPTOR_P(adapter, slot_num) == NULL){ - RINGMAP_ERROR(Pointer to descriptor is NULL); - goto fail; - } - /* Now if everything is Ok, we can initialize ring pointers */ - ring->slot[slot_num].mbuf.kern = - (vm_offset_t)GET_MBUF_P(adapter, slot_num); - ring->slot[slot_num].mbuf.phys = - (bus_addr_t)vtophys(GET_MBUF_P(adapter, slot_num)); - ring->slot[slot_num].packet.kern = - (vm_offset_t)GET_PACKET_P(adapter, slot_num); - ring->slot[slot_num].packet.phys = - (bus_addr_t)vtophys(GET_PACKET_P(adapter, slot_num)); + co->hw_rx_ring = &adapter->hw; + co->hw_tx_ring = &adapter->hw; - ring->slot[slot_num].descriptor.kern = - (vm_offset_t)GET_DESCRIPTOR_P(adapter, slot_num); - ring->slot[slot_num].descriptor.phys = - (bus_addr_t)vtophys(GET_DESCRIPTOR_P(adapter, slot_num)); + co->rx_buffers = adapter->rx_buffer_area; + co->tx_buffers = adapter->tx_buffer_area; - return (0); + co->rx_desc_base = adapter->rx_desc_base; + co->tx_desc_base = adapter->tx_desc_base; -fail: - RINGMAP_ERROR(Probably you have to do: ifconfig up); - return (-1); -} - - -/* Print the values from RDT and RDH */ -int -rm_8254_print_ring_pointers(struct adapter *adapter) -{ - unsigned int rdt, rdh; - struct ringmap *rm = NULL; - - rm = adapter->rm; - - if (rm == NULL) - goto out; - - rdh = RINGMAP_HW_READ_HEAD(adapter); - rdt = RINGMAP_HW_READ_TAIL(adapter); - - printf("\n== +++++++++ RING POINTERS ++++++++++++ \n"); - printf("== + HW HEAD = %d (KERN POINTER)\n", rdh); - printf("== + HW TAIL = %d (USER POINTER)\n", rdt); - printf("== ++++++++++++++++++++++++++++++++++++++ \n\n"); - -out: - return (0); -} - - -/* 8254x controllers have not multiqueue support: que = NULL */ -int -rm_8254_set_queue(struct capt_object *co, unsigned int i) -{ - /* No multiqueue for 8254 */ - co->que = NULL; + /* Interrupt context is adapter structure. Look in if_lem.h */ + co->intr_context = device_get_softc(co->rm->dev); return (0); } ==== //depot/projects/soc2010/ringmap/current/sys/net/ringmap.c#49 (text+ko) ==== @@ -45,7 +45,10 @@ void print_capt_obj(struct capt_object *); struct ringmap * cdev2ringmap(struct cdev *); struct ringmap * dev2ringmap(device_t); -int ringmap_filter(struct capt_object *, int); +void ringmap_bpf_filter(struct capt_object *, int); +void per_packet_iteration(struct capt_object *, int ); +struct capt_object * ringmap_delayed_isr(void *context, struct ringmap *rm); +int set_slot(struct capt_object *co, unsigned int slot_num); d_open_t ringmap_open; d_close_t ringmap_close; @@ -66,9 +69,11 @@ static struct ringmap_global_list ringmap_list_head = SLIST_HEAD_INITIALIZER(ringmap_list_head); + /* - * Will called from if_em.c before returning from - * em_attach() function. + * The function should be called from attach function of generic network driver. + * Here the ringmap structure is allocated and the character special device for + * the communication with user is created. */ struct ringmap * ringmap_attach(device_t dev, struct ringmap_functions *rf) @@ -77,9 +82,9 @@ RINGMAP_FUNC_DEBUG(begin); + /* Allocate ringmap */ MALLOC(rm, struct ringmap *, sizeof(struct ringmap), M_DEVBUF, (M_ZERO | M_WAITOK)); - if (rm == NULL) { RINGMAP_ERROR(Can not allocate space for ringmap structure); return (NULL); @@ -87,10 +92,10 @@ /* * Create char device for communication with user-space. The user-space - * process wich want to capture packets should first open this device. + * process wich want to capture packets first opens this device. * Then, by syscalls on this device it will: * - get physical adresses of packet buffers for mapping them in its - * virtual memory space + * virtual memory * * - controll packet capturing: start, stop, sleep to wait for packets. */ @@ -99,41 +104,55 @@ device_get_nameunit(dev)); if (rm->cdev == NULL) { RINGMAP_ERROR(Can not create char device); - contigfree(rm, sizeof(struct ringmap), M_DEVBUF); + FREE(rm, M_DEVBUF); return (NULL); } /* - * Tell to ringmap which hardware and driver speciffic functions - * should it use + * Set the hardware and driver speciffic functions */ rm->funcs = rf; - /* Store adapters device structure by ringmap */ + /* Store interface device structure in ringmap */ rm->dev = dev; - /* Initialize the list of capturing objects */ + /* + * Initialize the list of capturing objects. Each object represents the + * thread that capture traffic and its ring. + */ SLIST_INIT(&rm->object_list); - /* Insert ringmap in the global list */ + /* Insert ringmap structure into the list */ SLIST_INSERT_HEAD(&ringmap_list_head, rm, entries); /* Init the mutex to protecting our data */ RINGMAP_LOCK_INIT(rm, device_get_nameunit(dev)); + /* + * Set default functions if the generic driver's specific functions are not + * set + */ + if (rm->funcs->delayed_isr == NULL) + rm->funcs->delayed_isr = ringmap_delayed_isr; + + if (rm->funcs->per_packet_iteration == NULL) + rm->funcs->per_packet_iteration = per_packet_iteration; + + RINGMAP_FUNC_DEBUG(end); /* * Return ringmap pointer to the generic driver. Generic driver should - * store the pointer in the adapter structure + * store the pointer in the adapter structure in order to be able to access + * ringmap */ return (rm); } /* - * Should be called from driver detach function. It is a little dangerous - * place. Probably we shoul protect our data here with mutexes. + * Should be called from driver's detach function. It is a little dangerous + * place - probably we shoul protect our code here with locks!!! */ int ringmap_detach(device_t dev) @@ -194,7 +213,7 @@ rm = cdev2ringmap(cdev); if ( rm == NULL ) { - RINGMAP_ERROR(Null pointer to ringmap structure); + RINGMAP_ERROR(Could not get the pointer to ringmap structure); return (EIO); } @@ -237,7 +256,7 @@ } ring->size = SLOTS_NUMBER; - ring->pid = td->td_proc->p_pid; + ring->pid = td->td_proc->p_pid; /* Unneeded thing. TODO: Replace it with somth more resonable */ co->ring = ring; co->td = td; @@ -258,7 +277,7 @@ /* Init ring-slots with mbufs and packets adrresses */ for (i = 0 ; i < SLOTS_NUMBER ; i++) { - if (rm->funcs->set_slot(co, i) == -1){ + if (set_slot(co, i) == -1){ RINGMAP_ERROR(Ring initialization failed!); contigfree(ring, sizeof(struct ring), M_DEVBUF); @@ -273,7 +292,6 @@ /* * Insert the capturing object in the single linked list - * the head of the list is in the ringmap structure */ SLIST_INSERT_HEAD(&rm->object_list, co, objects); @@ -324,9 +342,8 @@ /* - * Callback of ringmap_close() - * Free memory allocated for capturing object and remove the - * capturing object from the list. + * Callback of ringmap_close() Free memory allocated for capturing object and + * remove the capturing object from the list. */ void clear_capt_object(void * data) @@ -336,15 +353,12 @@ RINGMAP_FUNC_DEBUG(start); - if (data != NULL) { - co = (struct capt_object *)data; + co = (struct capt_object *)data; + + if (co != NULL) { RINGMAP_LOCK(co->rm); - /* to be completely sure */ - if (co == NULL) - goto out; - rm = co->rm; #if (__RINGMAP_DEB) printf("[%s] Object to delete:\n", __func__); @@ -357,12 +371,12 @@ FREE(co, M_DEVBUF); data = co = NULL; - if (rm->open_cnt) { + if (rm->open_cnt > 0) { --rm->open_cnt; } else { RINGMAP_WARN(Incorrect value of rm->open_cnt); } -out: + RINGMAP_UNLOCK(rm); } else { @@ -433,15 +447,17 @@ struct ringmap *rm = NULL; struct capt_object *co = NULL; vm_paddr_t phys_ring_addr; + int error; RINGMAP_FUNC_DEBUG(start); /* Get pointer to the ringmap structure */ rm = cdev2ringmap(cdev); - if (devfs_get_cdevpriv((void **)&co)) { - RINGMAP_ERROR(Can not get capturing object); - return(EIO); + error = devfs_get_cdevpriv((void **)&co); + if (error) { + RINGMAP_ERROR(Can not access private data); + return(error); } if (co->td != curthread ){ @@ -481,9 +497,10 @@ printf("[%s] pid = %d\n", __func__, td->td_proc->p_pid); #endif - if (devfs_get_cdevpriv((void **)&co)) { + err = devfs_get_cdevpriv((void **)&co); + if (err != 0) { RINGMAP_IOCTL(Error! Can not get private data!); - return (ENODEV); + return (err); } rm = co->rm; @@ -496,8 +513,8 @@ /* Count how many times we wait for new packets */ co->ring->user_wait_kern++; - /* Set adapter TAIL register */ - rm->funcs->sync_tail(co); + /* Set adapter's TAIL register */ + rm->funcs->set_tail(co->ring->userrp, co->hw_rx_ring); #if (RINGMAP_IOCTL_DEB) print_capt_obj(co); @@ -506,7 +523,7 @@ /* * In the time: from user has called ioctl() until now could * come the new packets. It means, before we are going to sleep - * it makes a sence to check if we really must do it :) + * it makes a sence to check if we really must do it */ while (RING_IS_EMPTY(co->ring)) { RINGMAP_IOCTL(Sleep and wait for new packets); @@ -514,7 +531,7 @@ err = tsleep(co->ring, (PRI_MAX_ITHD) | PCATCH, "ioctl", 0); - /* go in user-space by catching signal */ + /* go back in user-space by catching signal */ if (err) goto out; } @@ -523,7 +540,7 @@ /* Synchronize sowftware ring-tail with hardware-ring-tail (RDT) */ case IOCTL_SYNC_TAIL: RINGMAP_LOCK(rm); - rm->funcs->sync_tail(co); + rm->funcs->set_tail(co->ring->userrp, co->hw_rx_ring); RINGMAP_UNLOCK(rm); break; @@ -531,7 +548,7 @@ bpf_prog = (struct bpf_program *)data; flen = bpf_prog->bf_len; if (flen > BPF_MAXINSNS) { - RINGMAP_ERROR("IOCTL_SETFILTER"); + RINGMAP_ERROR("bf_len > BPF_MAXINSNS"); err = EINVAL; goto out; } @@ -540,7 +557,7 @@ fcode = (struct bpf_insn *)malloc(size, M_BPF, M_WAITOK); if (copyin((caddr_t)bpf_prog->bf_insns, (caddr_t)fcode, size) == 0 && - bpf_validate(fcode, (int)flen)) { + bpf_validate(fcode, (int)flen)) { co->fcode = (struct bpf_insn *)fcode; } else { RINGMAP_ERROR("Could not set filter"); @@ -548,7 +565,12 @@ err = EINVAL; goto out; } - + + /* + * Everything went Ok. Set the filtering function + * Think about hardware support for packet filtering! + */ + co->rm->funcs->pkt_filter = ringmap_bpf_filter; break; default: @@ -564,22 +586,102 @@ } -/* Paket filtering */ -int -ringmap_filter(struct capt_object *co, int slot_num) +int +set_slot(struct capt_object *co, unsigned int slot_num) +{ + struct ring *ring = co->ring;; + struct ringmap *rm = co->rm; + +#if (__RINGMAP_DEB) + printf("[%s] Set slot: %d\n", __func__, slot_num); +#endif + + /* Now if everything is Ok, we can initialize ring pointers */ + ring->slot[slot_num].mbuf.kern = + (vm_offset_t)rm->funcs->get_mbuf(co->rx_buffers, slot_num); + ring->slot[slot_num].mbuf.phys = + (bus_addr_t)vtophys(ring->slot[slot_num].mbuf.kern); + + ring->slot[slot_num].packet.kern = + (vm_offset_t)rm->funcs->get_packet(co->rx_buffers, slot_num); + ring->slot[slot_num].packet.phys = + (bus_addr_t)vtophys(ring->slot[slot_num].packet.kern); + + return (0); +} + + +struct capt_object * +ringmap_delayed_isr(void *context, struct ringmap *rm) +{ + struct capt_object *co = NULL; + struct timeval last_ts; + + RINGMAP_INTR(start); + + RINGMAP_LOCK(rm); + /* Do the next steps only if there is capturing process */ + if (rm->open_cnt > 0) { + + /* TODO: do it through our set_timestamp() */ + getmicrotime(&last_ts); + + SLIST_FOREACH(co, &rm->object_list, objects) { + if (co->intr_context == context) { +#if (RINGMAP_INTR_DEB) + PRINT_RING_PTRS(co->ring); +#endif + rm->funcs->set_tail(co->ring->userrp, co->hw_rx_ring); + co->ring->last_ts = last_ts; + ++co->ring->intr_num; + break; + } + } + } + RINGMAP_UNLOCK(rm); + + RINGMAP_INTR(end); + + return(co); +} + + +void +per_packet_iteration(struct capt_object *co, int slot_num) +{ + struct ringmap *rm = co->rm; + + RINGMAP_INTR(start); + + co->ring->slot[slot_num].is_ok = 1; + co->ring->slot[slot_num].intr_num = co->ring->intr_num; + + if (rm->funcs->pkt_filter != NULL) + rm->funcs->pkt_filter(co, slot_num); + + co->ring->kernrp = slot_num; +#ifdef RINGMAP_TIMESTAMP + co->ring->slot[slot_num].ts = co->ring->last_ts; +#endif +#if (RINGMAP_INTR_DEB) + PRINT_SLOT(co->ring, slot_num); +#endif + + RINGMAP_INTR(end); +} + + +/* Paket filtering: wrapper around bpf_filter() */ +void +ringmap_bpf_filter(struct capt_object *co, int slot_num) { struct mbuf *mb = (struct mbuf *)K_MBUF(co->ring, slot_num); unsigned int pktlen = mb->m_len, slen; if (co->fcode != NULL) { slen = bpf_filter(co->fcode, (u_char *)mb, pktlen, 0); - if (slen) - co->ring->slot[slot_num].filtered = 1; - else - co->ring->slot[slot_num].filtered = 0; + co->ring->slot[slot_num].filtered = (slen + 1) ? slen:0; } - - return (0); } @@ -592,11 +694,6 @@ printf("=== Ring Kernel Addr:0x%X\n", (unsigned int)co->ring); - - /* Print addr of que only if multiqueue supported */ - if (co->que != NULL) - printf("=== Queue Kernel Addr:0x%X\n\n", - (unsigned int)co->que); } else { RINGMAP_WARN(NULL pointer: capturing object); } @@ -612,7 +709,6 @@ if (rm->dev == dev) return(rm); } - return(rm); } ==== //depot/projects/soc2010/ringmap/current/sys/net/ringmap.h#49 (text+ko) ==== @@ -1,4 +1,5 @@ -#define RING_SAFTY_MARGIN 2 +/* minimal distance between TAIL and HEAD */ +#define RING_SAFTY_MARGIN 1 /* * value for number of descriptors (a.k.a. slots in the ringbuffer) @@ -7,6 +8,7 @@ /* * Prefix for name of device (for example /dev/ringmap0 will full name) + * currently not used */ #define RINGMAP_DEVICE "ringmap" @@ -24,7 +26,7 @@ */ #define DEV_ID 0 -/* Enable/Disable Transiv. If 0, then the adapter will only receive pkts */ +/* Enable/Disable tranceive. If 0, then receive only */ #define RINGMAP_TX_ENABLE 0 /* 1 - enable time stamping in the driver */ @@ -40,10 +42,9 @@ }; /* - * This structure represents the ring slot. Each slot contains three - * entities: descriptor, mbuf and packet. The descriptore represents - * the hardware view of of packet. Mbuf represents the kernel view of - * packet. The packet represents the buffer where the packet data placed. + * This structure represents the ring slot. Each slot contains three entities: + * mbuf and packet. Mbuf represents the kernel view of packet. The packet + * represents the buffer where the packet data is placed. * * Each entity is of type 'struct address'. Struct 'address' contains * three addresses: physical-, kernel- and user-address. We need to store @@ -51,7 +52,6 @@ */ struct ring_slot { - struct address descriptor; struct address mbuf; struct address packet; @@ -85,19 +85,17 @@ struct ring { /* - * kernrp - ring HEAD. Should be changed ONLY in driver. And should be - * synchronized with the adapter-ring-HEAD register. Adapter increments - * the value in its HEAD-register after storing the incomming packets - * in the RAM. The driver should in the ISR check the value in the - * adapter-HEAD-register and set this value in kernrp. + * kernrp - ring HEAD. Must be changed ONLY in driver through synchronizing + * with ring-HEAD controller register. Adapter increments the value in its + * HEAD-register after storing the incomming packets in the RAM. The driver + * is responsible for synchronization kernrp with HEAD-register. */ unsigned int volatile kernrp; /* - * userrp - ring TAIL. Should be incremented by user space software after - * reading the slots with a new received packets. The driver, while - * executing ISR shoud check the value in userrp and set this value in - * the adapter-TAIL-register. + * userrp - ring TAIL. Must be incremented only in user space after + * reading a slot with a new received packet. The driver, while executing + * ISR shoud check userrp and set this value in the adapter-TAIL-register. */ unsigned int volatile userrp; @@ -117,7 +115,7 @@ unsigned long long kern_wait_user; /* - * Number of times the user process bumps into the HEAD. + * Number of times the TAIL bumps into the HEAD. * * A.K.A. User process has read everything there is to read in the ring. */ @@ -138,7 +136,7 @@ /* TODO: use other ID. Using PID is a wrong way */ unsigned int pid; - /* Array of slots */ + /* Array of slots (A.K.A packet buffers) */ struct ring_slot volatile slot[SLOTS_NUMBER]; }; @@ -266,6 +264,8 @@ #endif #ifndef __RINGMAP_DEB +#define __RINGMAP_DEB 0 +#elif #define __RINGMAP_DEB 1 #endif @@ -346,5 +346,5 @@ #ifdef _KERNEL -#include <net/ringmap_kernel.h> +#include "ringmap_kernel.h" #endif ==== //depot/projects/soc2010/ringmap/current/sys/net/ringmap_kernel.h#19 (text+ko) ==== @@ -5,10 +5,30 @@ struct thread *td; struct ring *ring; - void *que; + + /* + * Pointers to the structures allocated in the generic driver for accesisng + * hardware registers related to the rx/tx queues associated with our + * capturing object. + */ + void *hw_rx_ring, *hw_tx_ring; + + /* + * Pointer to the arrays allocated in the generic driver for accessing + * rx/tx buffers and descriptors. + */ + void *rx_buffers, *tx_buffers, *rx_desc_base, *tx_desc_base; + /* Packet filtering code. */ struct bpf_insn *fcode; + /* + * Source of interrupts affecting our capturing object. It can be adapter, + * device or queue structure. + */ + void *intr_context; + + /* Let's concatenate our objects */ SLIST_ENTRY(capt_object) objects; }; @@ -20,20 +40,19 @@ * device and driver structures */ struct ringmap { - /* Device structure of network adapter */ + /* Device structure */ device_t dev; - /* Char device for communications between user and kernel spaces */ + /* Char device for communications between user and ringmap */ struct cdev *cdev; - /* Number of processes that opened cdev. + /* Number of threads that opened cdev. * A.K.A. number of capturing objects */ uint32_t volatile open_cnt; /* Hardware dependent functions */ struct ringmap_functions *funcs; - /* Mutex that should protect the data allocated in the ring */ struct mtx ringmap_mtx; /* Head of the list of capturing objects */ @@ -49,59 +68,60 @@ struct ringmap_functions { >>> TRUNCATED FOR MAIL (1000 lines) <<<
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201010172043.o9HKhV62043651>