PERFORCE change 184838 for review
Alexandre Fiveg
afiveg at FreeBSD.org
Sun Oct 17 20:43:32 UTC 2010
http://p4web.freebsd.org/@@184838?ac=10
Change 184838 by afiveg at 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) <<<
More information about the p4-projects
mailing list