PERFORCE change 183300 for review

Alexandre Fiveg afiveg at FreeBSD.org
Fri Sep 3 12:02:51 UTC 2010


http://p4web.freebsd.org/@@183300?ac=10

Change 183300 by afiveg at cottonmouth on 2010/09/03 12:01:58

	Added filtering using kernel BPF: ringmap.c ringmap_filter(). It needs to be reviewed! It works in my testbed but I guess it is not properly implemented so it works in all possible cases. ringmap_filter sets BPFIF_LOCK then tries to find bpf_d belonging to the process that capture from current ring. Then sets BPFD_LOCK and call bpf_filter(). If bpf_filter returns > 0, then set ring->slot->filtered=1. User-space process cheks "filtered" value to know whether the packet was accepted by BPF. 

Affected files ...

.. //depot/projects/soc2010/ringmap/current/contrib/libpcap/pcap-bpf.c#18 edit
.. //depot/projects/soc2010/ringmap/current/contrib/libpcap/pcap-int.h#18 edit
.. //depot/projects/soc2010/ringmap/current/contrib/libpcap/pcap.c#21 edit
.. //depot/projects/soc2010/ringmap/current/contrib/libpcap/ringmap_pcap.c#33 edit
.. //depot/projects/soc2010/ringmap/current/sys/dev/e1000/if_lem.c#34 edit
.. //depot/projects/soc2010/ringmap/current/sys/dev/e1000/if_lem.h#22 edit
.. //depot/projects/soc2010/ringmap/current/sys/dev/e1000/ringmap_8254.c#33 edit
.. //depot/projects/soc2010/ringmap/current/sys/dev/e1000/ringmap_8254.h#31 edit
.. //depot/projects/soc2010/ringmap/current/sys/dev/e1000/ringmap_e1000.h#23 edit
.. //depot/projects/soc2010/ringmap/current/sys/dev/ixgbe/ringmap_8259.h#16 edit
.. //depot/projects/soc2010/ringmap/current/sys/dev/ixgbe/ringmap_ixgbe.c#17 edit
.. //depot/projects/soc2010/ringmap/current/sys/net/ringmap.c#47 edit
.. //depot/projects/soc2010/ringmap/current/sys/net/ringmap.h#47 edit
.. //depot/projects/soc2010/ringmap/current/sys/net/ringmap_kernel.h#17 edit
.. //depot/projects/soc2010/ringmap/scripts/build_ringmap.sh#29 edit
.. //depot/projects/soc2010/ringmap/scripts/set_ringmap.sh#30 edit
.. //depot/projects/soc2010/ringmap/scripts/tailf_ringmap_msgs.sh#24 edit
.. //depot/projects/soc2010/ringmap/tests/libpcap/easy_pcap.c#15 edit

Differences ...

==== //depot/projects/soc2010/ringmap/current/contrib/libpcap/pcap-bpf.c#18 (text+ko) ====


==== //depot/projects/soc2010/ringmap/current/contrib/libpcap/pcap-int.h#18 (text+ko) ====


==== //depot/projects/soc2010/ringmap/current/contrib/libpcap/pcap.c#21 (text+ko) ====


==== //depot/projects/soc2010/ringmap/current/contrib/libpcap/ringmap_pcap.c#33 (text+ko) ====

@@ -227,36 +227,47 @@
 {
 	unsigned int ws,  wait_flag = 1, tmp_dist; 
 	unsigned int curr_slot;
+	int err_sleep, slen;
 	struct mbuf *mb; 
 	caddr_t datap; 
 	struct pcap_pkthdr pkthdr;
 	struct ring *ring;
 
+
 	RINGMAP_FUNC_DEBUG(start);
 
+	if (p->break_loop) {
+		p->break_loop = 0;
+		return (-2);
+	}
+
 	if (p->ring == NULL){
 		RINGMAP_ERROR(Ring is not allocated);
-
 		exit (1);
 	}
 
 	ring = p->ring;
 
-	if (p->break_loop) {
-		p->break_loop = 0;
-		return (-2);
-	}
-
-	while ( RING_IS_EMPTY(ring) ) {
+	/* stay here as long as the ring is empty */
+	while (RING_IS_EMPTY(ring)) {
 
 #if (__RINGMAP_DEB)
 		PRINT_RING_PTRS(ring);
 		RINGMAP_FUNC_DEBUG(Ring is empty. Sleep...);
 #endif 
 		/* Sleep and wait for new incoming packets */
-		ioctl(ringmap_cdev_fd, IOCTL_SLEEP_WAIT);
+		err_sleep = ioctl(ringmap_cdev_fd, IOCTL_SLEEP_WAIT);
+
+		/* catching signals */
+		if (err_sleep) {
+			if (errno == EINTR) {
+				pcap_close(p);
+				exit(0);
+			}
+		}
 	}
 
+	/* Ok, if we are here the ring shouldn't be empty, let's capture */
 #if (__RINGMAP_DEB)
 		RINGMAP_FUNC_DEBUG(Ring is NOT empty:);
 		PRINT_RING_PTRS(ring);
@@ -275,7 +286,18 @@
 				return (cnt - ws);
 		}
 
+		/* Slot we want to check */
 		curr_slot = R_MODULO( SW_TAIL(ring) + 1 );
+
+		mb = (struct mbuf *)U_MBUF(ring, curr_slot);
+		datap = (caddr_t)U_PACKET(ring, curr_slot);
+		pkthdr.caplen = pkthdr.len = mb->m_len;
+		pkthdr.ts = ring->slot[curr_slot].ts;
+
+		/* 
+		 * ringmap-Driver tell us whether the slot contains 
+		 * a good packet 
+		 */
 		if (ring->slot[curr_slot].is_ok == 0) {
 #if (__RINGMAP_DEB)
 			printf("Slot %d was not accepted by driver!\n", curr_slot);
@@ -283,16 +305,30 @@
 			goto out;
 		}
 
-		mb = (struct mbuf *)U_MBUF(ring, curr_slot);
+		/* Packet filtering */
+		if (p->md.use_bpf) {
+			/* Filtered in Kernel */
+			if (ring->slot[curr_slot].filtered == 0) {
+#if (__RINGMAP_DEB)
+				printf("Slot %d was not filtered by kernel bpf!\n", curr_slot);
+#endif 
+				goto out;
+			}
+		} else {
+			/* Filtering in user-space */
+		    slen = bpf_filter(p->fcode.bf_insns, datap, mb->m_len, mb->m_len);
+			if (!slen)
+				goto out;
+		}
 
-		pkthdr.ts = ring->slot[curr_slot].ts;
-		pkthdr.caplen = pkthdr.len = mb->m_len;
-		datap = (caddr_t)U_PACKET(ring, curr_slot);
-
 		ring->pkt_counter++;
 		--ws;
 
+#if (__RINGMAP_DEB)
 		PRINT_PKT_BYTES(datap, curr_slot);	
+#endif 
+
+		/* callback function */
 		(*callback)(user, &pkthdr, datap);
 
 #if (__RINGMAP_DEB)

==== //depot/projects/soc2010/ringmap/current/sys/dev/e1000/if_lem.c#34 (text+ko) ====


==== //depot/projects/soc2010/ringmap/current/sys/dev/e1000/if_lem.h#22 (text+ko) ====


==== //depot/projects/soc2010/ringmap/current/sys/dev/e1000/ringmap_8254.c#33 (text+ko) ====

@@ -31,6 +31,7 @@
 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 ifnet *, struct capt_object *, int);
 
 
 struct ringmap_functions ringmap_8254_f = {
@@ -116,27 +117,6 @@
 	RINGMAP_INTR(end);
 }
 
-/* Returns the ring which TAIL pointer is mostly near to to the HEAD(RDH) */
-struct capt_object *
-rm_8254_find_next(struct adapter *adapter)
-{
-	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);
-}
 
 void 
 rm_8254_delayed_interrupt_per_packet(void *context, int slot_num)
@@ -155,12 +135,13 @@
 		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(adapter->ifp, co, slot_num);
 
 #ifdef RINGMAP_TIMESTAMP
 			co->ring->slot[slot_num].ts = co->ring->last_ts;
 #endif 
-
-#if (__RINGMAP_DEB)
+#if (RINGMAP_INTR_DEB)
 			PRINT_SLOT((co->ring), (slot_num));
 #endif 
 		}
@@ -170,6 +151,30 @@
 }
 
 
+/* Returns the ring which TAIL pointer is mostly near to to the HEAD(RDH) */
+struct capt_object *
+rm_8254_find_next(struct adapter *adapter)
+{
+	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)
 {

==== //depot/projects/soc2010/ringmap/current/sys/dev/e1000/ringmap_8254.h#31 (text+ko) ====


==== //depot/projects/soc2010/ringmap/current/sys/dev/e1000/ringmap_e1000.h#23 (text+ko) ====


==== //depot/projects/soc2010/ringmap/current/sys/dev/ixgbe/ringmap_8259.h#16 (text+ko) ====


==== //depot/projects/soc2010/ringmap/current/sys/dev/ixgbe/ringmap_ixgbe.c#17 (text+ko) ====


==== //depot/projects/soc2010/ringmap/current/sys/net/ringmap.c#47 (text+ko) ====

@@ -21,6 +21,8 @@
 #include <net/if_var.h>
 #include <net/if_types.h>
 #include <net/if_media.h>
+#include <net/bpf.h>
+#include <net/bpfdesc.h>
 
 #include <vm/vm.h>
 #include <vm/pmap.h>
@@ -43,6 +45,7 @@
 void print_capt_obj(struct capt_object *);
 struct ringmap * cdev2ringmap(struct cdev *);
 struct ringmap * dev2ringmap(device_t);
+int ringmap_filter(struct ifnet *, struct capt_object *, int);
 
 d_open_t	ringmap_open;
 d_close_t	ringmap_close;
@@ -74,8 +77,9 @@
 
 	RINGMAP_FUNC_DEBUG(begin);
 
-	rm = (struct ringmap *) contigmalloc (sizeof(struct ringmap), 
-							M_DEVBUF, M_ZERO, 0, -1L, PAGE_SIZE, 0);
+	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);
@@ -119,6 +123,10 @@
 
 	RINGMAP_FUNC_DEBUG(end); 
 
+	/* 
+	 * Return ringmap pointer to the generic driver. Generic driver should
+	 * store the pointer in the adapter structure
+	 */
 	return (rm);	
 }
 
@@ -144,7 +152,6 @@
 	/* Remove all capturing objects associated with ringmap */
     while (!SLIST_EMPTY(&rm->object_list)) {
 	    co = SLIST_FIRST(&rm->object_list);
-	    SLIST_REMOVE_HEAD(&rm->object_list, objects);
 	    clear_capt_object((void *)co);
     }
 
@@ -157,7 +164,7 @@
 	/* And remove ringmap from global list */
 	SLIST_REMOVE(&ringmap_list_head, rm, ringmap, entries);
 	
-	contigfree(rm, sizeof(struct ringmap), M_DEVBUF);
+	FREE(rm, M_DEVBUF);
 
 	RINGMAP_FUNC_DEBUG(end);
 
@@ -193,7 +200,7 @@
 
 	RINGMAP_LOCK(rm);
 
-	/* TODO: set max number of threads in the ringmap struct as a variable */
+	/* TODO: set max number of threads in the ringmap struct as a member */
 	if (rm->open_cnt == RINGMAP_MAX_THREADS) {
 		RINGMAP_ERROR(Can not open device!);
 		err = EIO; goto out;
@@ -222,7 +229,7 @@
 	 * create the capturing object wich will represent 
 	 * current thread and packets ring 
 	 */
-	MALLOC(	co, struct capt_object *, 
+	MALLOC(co, struct capt_object *, 
 			sizeof(struct capt_object), M_DEVBUF, (M_ZERO | M_WAITOK));
 	if ( co == NULL ){
 		contigfree(ring, sizeof(struct ring), M_DEVBUF);
@@ -249,7 +256,7 @@
 	}
 #endif 
 
-	/* Init ring-slots  with mbufs and packets adrresses */
+	/* Init ring-slots with mbufs and packets adrresses */
 	for (i = 0 ; i < SLOTS_NUMBER ; i++) {
 		if (rm->funcs->set_slot(co, i) == -1){
 			RINGMAP_ERROR(Ring initialization failed!);
@@ -274,7 +281,7 @@
 	 * Store capturing object as private data. So we can access our capturing
 	 * object in other syscalls, e.g. read, close, etc... 
 	 */
-	if ( devfs_set_cdevpriv((void *)co, clear_capt_object) ) {
+	if (devfs_set_cdevpriv((void *)co, clear_capt_object)) {
 		RINGMAP_ERROR(Can not set private data!);
 
 		contigfree(ring, sizeof(struct ring), M_DEVBUF);
@@ -283,7 +290,7 @@
 		err = EIO; goto out;
 	}
 
-	rm->open_cnt++;
+	++rm->open_cnt;
 
 #if (__RINGMAP_DEB)
 	print_capt_obj(co);
@@ -299,6 +306,12 @@
 }
 
 
+/* 
+ * Do nothing here. This func will called when the last thread calls close(2).
+ * But the callback: clear_capt_object() will be called every time by
+ * close(2). Attention!!! - If the last thread call close(2) first will be
+ * ringmap_close() called and then clear_capt_object() !!! 
+ */
 int
 ringmap_close(struct cdev *cdev, int flag, int otyp, struct thread *td)
 {
@@ -325,9 +338,14 @@
 
 	if (data != NULL) {
 		co = (struct capt_object *)data;
+
+		RINGMAP_LOCK(co->rm);
+
+		/* to be completely sure */
+		if (co == NULL) 
+			goto out;
+
 		rm = co->rm;
-
-		RINGMAP_LOCK(rm);
 #if (__RINGMAP_DEB)
 		printf("[%s] Object to delete:\n", __func__);
 		print_capt_obj(co);
@@ -337,9 +355,14 @@
 
 		SLIST_REMOVE(&rm->object_list, co, capt_object, objects);
 		FREE(co, M_DEVBUF);
-		data = NULL;
+		data = co = NULL;
 
-		rm->open_cnt--;
+		if (rm->open_cnt) {
+			--rm->open_cnt;
+		} else {
+			RINGMAP_WARN(Incorrect value of rm->open_cnt);
+		}
+out: 
 		RINGMAP_UNLOCK(rm);
 
 	} else {
@@ -485,8 +508,12 @@
 			while (RING_IS_EMPTY(co->ring)) {
 				RINGMAP_IOCTL(Sleep and wait for new packets);
 
-				err_sleep = tsleep(co->ring, 
+				err = tsleep(co->ring, 
 						(PRI_MAX_ITHD) | PCATCH, "ioctl", 0);
+
+				/* go in user-space by catching signal */
+				if (err)
+					goto out;
 			}
 		break;
 
@@ -502,12 +529,49 @@
 			return (ENODEV);
 	}   	
  
+out: 
+
 	RINGMAP_IOCTL(end);
  
 	return (err);
 }
 
 
+/* Paket filtering */ 
+int 
+ringmap_filter(struct ifnet *rcvif, struct capt_object *co, int slot_num)
+{
+	struct bpf_if *bp = rcvif->if_bpf;
+	struct bpf_d *d = NULL;
+	struct mbuf *mb = (struct mbuf *)K_MBUF(co->ring, slot_num);
+	u_int pktlen = mb->m_len, slen;
+
+	BPFIF_LOCK(bp);
+
+	LIST_FOREACH(d, &bp->bif_dlist, bd_next) {
+		if (d->bd_pid == co->td->td_proc->p_pid)
+			break;
+	}
+	if (d != NULL) {
+		BPFD_LOCK(d);
+
+		printf("ifdname: %s\n", rcvif->if_dname);
+		++d->bd_rcount;
+		slen = bpf_filter(d->bd_rfilter, (u_char *)mb, pktlen, 0);
+		if (slen)
+			co->ring->slot[slot_num].filtered = 1;
+		else 
+			co->ring->slot[slot_num].filtered = 0;
+
+		BPFD_UNLOCK(d);
+	}
+
+	BPFIF_UNLOCK(bp);
+
+	return (0);
+}
+
+
 void 
 print_capt_obj(struct capt_object *co)
 {

==== //depot/projects/soc2010/ringmap/current/sys/net/ringmap.h#47 (text+ko) ====


==== //depot/projects/soc2010/ringmap/current/sys/net/ringmap_kernel.h#17 (text+ko) ====


==== //depot/projects/soc2010/ringmap/scripts/build_ringmap.sh#29 (text+ko) ====

@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/local/bin/bash
 
 RINGMAP_BUILD_DIR=../current/sys/modules/ringmap/
 LIBPCAP_BUILD_DIR=../current/lib/libpcap/
@@ -6,7 +6,7 @@
 make_ringmap() {
 	cd ${RINGMAP_BUILD_DIR}
 	make clean 
-	make || { echo "Error while compiling driver" ; return 1 ; }
+	make DEBUG_FLAGS=-g || { echo "Error while compiling driver" ; return 1 ; }
 	cd -
 }
 
@@ -37,22 +37,24 @@
 echo "=================================================================="
 echo
 
+[ ${1} == "ringmap" ] && exit 0
+
 # Build libpcap
 echo
-echo "MAKE libpcap FOR ringmap DRIVER:"
+echo "MAKE LIBPCAP FOR RINGMAP DRIVER:"
 echo "=================================================================="
 sleep 1
 make_libpcap
 if [ $? -eq 1 ]
-then 
+then
 	echo
 	echo "Stop building! Exit!"
 	exit 1;
 fi
 
 echo
-echo Everything seems to be Ok. 
-echo Now, for loading ringmap driver and for installing libpcap:
+echo Everything seems to be Ok.
+echo For loading ringmap driver and for installing libpcap do:
 echo sudo ./set_ringmap.sh
 echo
 

==== //depot/projects/soc2010/ringmap/scripts/set_ringmap.sh#30 (text+ko) ====


==== //depot/projects/soc2010/ringmap/scripts/tailf_ringmap_msgs.sh#24 (text+ko) ====


==== //depot/projects/soc2010/ringmap/tests/libpcap/easy_pcap.c#15 (text+ko) ====



More information about the p4-projects mailing list