simple examples of how to

Saturday, October 17, 2009

madwifi patches

1. add in-kernel-network-monitoring
2. add "report buffer full" from ieee80211_output to network kernel
3. buffer size control
4. 802.11e enabled with adhoc mode
5. worse than useless ttl-based packet filtering (beyond crap) who would use this?

the following

diff -Nru madwifi-original/ath/if_ath.c madwifi-new/ath/if_ath.c
--- madwifi-original/ath/if_ath.c 2009-10-05 17:25:39.000000000 +0200
+++ madwifi-new/ath/if_ath.c 2009-10-15 12:38:40.000000000 +0200
@@ -467,6 +467,8 @@
MODULE_PARM_DESC(ratectl, "Rate control algorithm [amrr|minstrel|onoe|sample], "
"defaults to '" DEF_RATE_CTL "'");

+static int iknm_portnum=30010;
+
#ifdef AR_DEBUG
static int ath_debug = 0;
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,52))
@@ -563,6 +565,213 @@
return f;
}

+/* jyyoo (jaeyong): in-kernel-network-monitoring */
+int thread_deliver_ath_hardstart(void* data)
+{
+ struct ath_softc* sc = (struct ath_softc*)data;
+
+ init_waitqueue_head(&sc->sc_queue_send);
+
+ sc->sc_kthread_send_alive = 1;
+ while( sc->sc_kthread_send_alive )
+ {
+ int ret;
+ int h, t;
+ int total_info;
+ int total_packet;
+ int debug_cnt=0;
+
+ mm_segment_t oldmm;
+
+ h = sc->sc_monitor_head;
+ t = sc->sc_monitor_tail;
+
+ if( h < t ) h += MAX_MPARAM;
+
+ total_info = h-t;
+
+ total_packet = total_info / MAX_MPARAM_PERPACKET;
+ if( total_info % MAX_MPARAM_PERPACKET ) total_packet += 1;
+
+ while( h != t )
+ {
+ debug_cnt ++;
+ if( debug_cnt > 30 ) {
+ printk("critical loop detected!!!\n");
+ break;
+ }
+ /* first determine iov_base */
+ sc->sc_iov_msg.iov_base = (char*)&sc->sc_monitor_param[t];
+
+ /* and then determine iov_len */
+ if( sc->sc_monitor_head > sc->sc_monitor_tail )
+ {
+ if( (h - t) > MAX_MPARAM_PERPACKET )
+ {
+ sc->sc_iov_msg.iov_len = MAX_MPARAM_PERPACKET * sizeof(struct monitor_param);
+ t+=MAX_MPARAM_PERPACKET;
+ }
+ else
+ {
+ sc->sc_iov_msg.iov_len = (h-t)*sizeof(struct monitor_param);
+ t = h;
+ }
+ }
+ else
+ {
+ int pre_t=t;
+ if( (h - t) > MAX_MPARAM_PERPACKET )
+ {
+ pre_t+=MAX_MPARAM_PERPACKET;
+ }
+ else
+ {
+ pre_t = h;
+ }
+
+ if( pre_t >= MAX_MPARAM )
+ {
+ sc->sc_iov_msg.iov_len = (MAX_MPARAM - t) * sizeof(struct monitor_param);
+ t = 0;
+ h -= MAX_MPARAM;
+ }
+ else
+ {
+ if( (h - t) > MAX_MPARAM_PERPACKET )
+ {
+ sc->sc_iov_msg.iov_len = MAX_MPARAM_PERPACKET * sizeof(struct monitor_param);
+ t+=MAX_MPARAM_PERPACKET;
+ }
+ else
+ {
+ sc->sc_iov_msg.iov_len = (h-t)*sizeof(struct monitor_param);
+ t = h;
+ }
+
+ }
+ }
+
+ oldmm = get_fs();
+ set_fs(KERNEL_DS);
+ if( (ret = sock_sendmsg( sc->sc_sock_mclient, &sc->sc_msghdr, sc->sc_iov_msg.iov_len )) < 0 )
+ {
+ printk("IKNM: send error: %d\n", ret);
+ }
+ set_fs(oldmm);
+ }
+ sc->sc_monitor_tail = h;
+ if( sc->sc_iknm_enable )
+ interruptible_sleep_on_timeout(&sc->sc_queue_send, HZ/20);
+ else
+ interruptible_sleep_on_timeout(&sc->sc_queue_send, HZ);
+ }
+ complete_and_exit(NULL, 0);
+ return 0;
+}
+/* jyyoo (jaeyong): in-kernel-network-monitoring */
+int thread_deliver_rx_tasklet(void* data)
+{
+ struct ath_softc* sc = (struct ath_softc*)data;
+
+ init_waitqueue_head(&sc->sc_recv_queue_send);
+
+ sc->sc_recv_kthread_send_alive = 1;
+ while( sc->sc_recv_kthread_send_alive )
+ {
+ int ret;
+ int h, t;
+ int total_info;
+ int total_packet;
+ int debug_cnt=0;
+
+ mm_segment_t oldmm;
+
+ h = sc->sc_recv_monitor_head;
+ t = sc->sc_recv_monitor_tail;
+
+ if( h < t ) h += MAX_MPARAM;
+
+ total_info = h-t;
+
+ total_packet = total_info / MAX_MPARAM_PERPACKET;
+ if( total_info % MAX_MPARAM_PERPACKET ) total_packet += 1;
+
+ while( h != t )
+ {
+ debug_cnt ++;
+ if( debug_cnt > 30 ) {
+ printk("critical loop detected!!!\n");
+ break;
+ }
+ /* first determine iov_base */
+ sc->sc_recv_iov_msg.iov_base = (char*)&sc->sc_recv_monitor_param[t];
+
+ /* and then determine iov_len */
+ if( sc->sc_recv_monitor_head > sc->sc_recv_monitor_tail )
+ {
+ if( (h - t) > MAX_MPARAM_PERPACKET )
+ {
+ sc->sc_recv_iov_msg.iov_len = MAX_MPARAM_PERPACKET * sizeof(struct monitor_param_recv);
+
+ t+=MAX_MPARAM_PERPACKET;
+ }
+ else
+ {
+ sc->sc_recv_iov_msg.iov_len = (h-t)*sizeof(struct monitor_param_recv);
+ t = h;
+ }
+ }
+ else
+ {
+ int pre_t=t;
+ if( (h - t) > MAX_MPARAM_PERPACKET )
+ {
+ pre_t+=MAX_MPARAM_PERPACKET;
+ }
+ else
+ {
+ pre_t = h;
+ }
+
+ if( pre_t >= MAX_MPARAM )
+ {
+ sc->sc_recv_iov_msg.iov_len = (MAX_MPARAM - t) * sizeof(struct monitor_param_recv);
+ t = 0;
+ h -= MAX_MPARAM;
+ }
+ else
+ {
+ if( (h - t) > MAX_MPARAM_PERPACKET )
+ {
+ sc->sc_recv_iov_msg.iov_len = MAX_MPARAM_PERPACKET * sizeof(struct monitor_param_recv);
+ t+=MAX_MPARAM_PERPACKET;
+ }
+ else
+ {
+ sc->sc_recv_iov_msg.iov_len = (h-t)*sizeof(struct monitor_param_recv);
+ t = h;
+ }
+ }
+ }
+ oldmm = get_fs();
+ set_fs(KERNEL_DS);
+ if( (ret = sock_sendmsg( sc->sc_recv_sock_mclient, &sc->sc_recv_msghdr, sc->sc_recv_iov_msg.iov_len )) < 0 )
+ {
+ printk("IKNM: send error: %d\n", ret);
+ }
+ set_fs(oldmm);
+ }
+ sc->sc_recv_monitor_tail = h;
+ if( sc->sc_iknm_enable )
+ interruptible_sleep_on_timeout(&sc->sc_recv_queue_send, HZ/2);
+ else
+ interruptible_sleep_on_timeout(&sc->sc_recv_queue_send, HZ);
+ }
+ complete_and_exit(NULL, 0);
+ return 0;
+}
+
+
/* Initialize ath_softc structure */

int
@@ -587,6 +796,10 @@

sc->sc_hwinfo = &generic_hw_info;

+ /* jyyoo add marker */
+ printk("jyyoo marker v.0.1.2\n");
+ ic->ic_enable_ttl_pf = 0;
+ ic->ic_adhoc_edca = 0;
/* Allocate space for dynamically determined maximum VAP count */
sc->sc_bslot =
kmalloc(ath_maxvaps * sizeof(struct ieee80211vap*), GFP_KERNEL);
@@ -1187,6 +1400,168 @@
sc->sc_noise_immunity = -1;
sc->sc_ofdm_weak_det = -1;

+ /* jyyoo (jaeyong): in-kernel-network-monitoring */
+
+ sc->sc_iknm_enable = 1;
+
+ /* just for the heads up */
+ printk("sizeof(struct timeval)=%d\n", sizeof(struct timeval));
+
+ /* default port number: 30001 */
+ sc->sc_port_number = 30001;
+ sc->sc_serv_addr.sin_family = AF_INET;
+ /* default monitor server ip address: 172.17.255.254 (panther) */
+ sc->sc_serv_addr.sin_addr.s_addr = (in_aton("172.17.255.254"));
+ sc->sc_serv_addr.sin_port = htons(sc->sc_port_number);
+
+ sc->sc_serv_addr2.sin_family = AF_INET;
+ sc->sc_serv_addr2.sin_addr.s_addr = htonl(INADDR_ANY);
+ sc->sc_serv_addr2.sin_port = htons(iknm_portnum++);
+ spin_lock_init(&sc->sc_send_lock);
+ sc->sc_monitor_head = 0;
+ sc->sc_monitor_tail = 0;
+ sc->dp_exchange_buffer_drop = 0;
+
+ if( sock_create(AF_INET, SOCK_DGRAM, 0, &sc->sc_sock_mclient) < 0 )
+ {
+ printk("IKNM: Error creating socket\n");
+ sc->sc_sock_mclient = NULL;
+ }
+ else
+ {
+
+ int i;
+ int ret;
+ mm_segment_t oldmm;
+
+ if( sc->sc_sock_mclient->ops->bind( sc->sc_sock_mclient,
+ (struct sockaddr*)&sc->sc_serv_addr2,
+ sizeof(sc->sc_serv_addr2) ) < 0 )
+ {
+ printk("IKNM: Error bind failed\n");
+
+ }
+ else
+ {
+
+ printk("IKNM: socket initiation succeeded; port %d addr: 172.17.255.254\n", sc->sc_port_number);
+
+ for( i=0; i<1024; i++ )
+ sc->sc_msgbuf[i] = i;
+
+
+ sc->sc_msghdr.msg_name = (struct sockaddr*)&sc->sc_serv_addr;
+ sc->sc_msghdr.msg_namelen = sizeof(sc->sc_serv_addr);
+ sc->sc_msghdr.msg_iov = &sc->sc_iov_msg;
+ sc->sc_msghdr.msg_iovlen = 1;
+ sc->sc_msghdr.msg_control = NULL;
+ sc->sc_msghdr.msg_controllen = 0;
+ sc->sc_msghdr.msg_flags = 0;
+
+ sc->sc_iov_msg.iov_base = sc->sc_msgbuf;
+ sc->sc_iov_msg.iov_len = 1024;
+
+ oldmm = get_fs();
+ set_fs(KERNEL_DS);
+
+
+ if( (ret = sock_sendmsg( sc->sc_sock_mclient, &sc->sc_msghdr, sc->sc_iov_msg.iov_len )) < 0 )
+ {
+ printk("IKNM: first send error: %d\n", ret);
+ }
+ else
+ {
+ printk("IKNM: first send succeeded %d\n", ret);
+ }
+
+ set_fs(oldmm);
+ }
+
+ }
+
+ sc->sc_kthread_send_alive = 0;
+
+ sc->sc_kthread_send = kthread_create( thread_deliver_ath_hardstart, sc, "iknm_MAC_monitor" );
+ wake_up_process(sc->sc_kthread_send);
+
+ /* default port number: 30001 */
+ sc->sc_recv_port_number = 30003;
+ sc->sc_recv_serv_addr.sin_family = AF_INET;
+ /* default monitor server ip address: 172.17.255.254 (panther) */
+ sc->sc_recv_serv_addr.sin_addr.s_addr = (in_aton("172.17.255.254"));
+ sc->sc_recv_serv_addr.sin_port = htons(sc->sc_recv_port_number);
+
+ sc->sc_recv_serv_addr2.sin_family = AF_INET;
+ sc->sc_recv_serv_addr2.sin_addr.s_addr = htonl(INADDR_ANY);
+ sc->sc_recv_serv_addr2.sin_port = htons(iknm_portnum++);
+ spin_lock_init(&sc->sc_recv_send_lock);
+ sc->sc_recv_monitor_head = 0;
+ sc->sc_recv_monitor_tail = 0;
+ sc->dp_exchange_buffer_drop = 0;
+
+ if( sock_create(AF_INET, SOCK_DGRAM, 0, &sc->sc_recv_sock_mclient) < 0 )
+ {
+ printk("IKNM: Error creating socket\n");
+ sc->sc_recv_sock_mclient = NULL;
+ }
+ else
+ {
+
+ int i;
+ int ret;
+ mm_segment_t oldmm;
+
+ if( sc->sc_recv_sock_mclient->ops->bind( sc->sc_recv_sock_mclient,
+ (struct sockaddr*)&sc->sc_recv_serv_addr2,
+ sizeof(sc->sc_recv_serv_addr2) ) < 0 )
+ {
+ printk("IKNM: Error bind failed\n");
+
+ }
+ else
+ {
+
+ printk("IKNM: socket initiation succeeded; port %d addr: 172.17.255.254 (monitor_param size:%d)\n", sc->sc_recv_port_number, sizeof(struct monitor_param_recv));
+
+ for( i=0; i<1024; i++ )
+ sc->sc_recv_msgbuf[i] = i;
+ sc->sc_recv_msghdr.msg_name = (struct sockaddr*)&sc->sc_recv_serv_addr;
+ sc->sc_recv_msghdr.msg_namelen = sizeof(sc->sc_recv_serv_addr);
+ sc->sc_recv_msghdr.msg_iov = &sc->sc_recv_iov_msg;
+ sc->sc_recv_msghdr.msg_iovlen = 1;
+ sc->sc_recv_msghdr.msg_control = NULL;
+ sc->sc_recv_msghdr.msg_controllen = 0;
+ sc->sc_recv_msghdr.msg_flags = 0;
+
+ sc->sc_recv_iov_msg.iov_base = sc->sc_recv_msgbuf;
+ sc->sc_recv_iov_msg.iov_len = 1024;
+
+ oldmm = get_fs();
+ set_fs(KERNEL_DS);
+
+
+ if( (ret = sock_sendmsg( sc->sc_recv_sock_mclient, &sc->sc_recv_msghdr, sc->sc_recv_iov_msg.iov_len )) < 0 )
+ {
+ printk("IKNM: first send error: %d\n", ret);
+ }
+ else
+ {
+ printk("IKNM: first send succeeded %d\n", ret);
+ }
+
+ set_fs(oldmm);
+ }
+
+ }
+
+ sc->sc_recv_kthread_send_alive = 0;
+
+ sc->sc_recv_kthread_send = kthread_create( thread_deliver_rx_tasklet, sc, "recv-iknm_MAC_monitor" );
+ wake_up_process(sc->sc_recv_kthread_send);
+
+
+ sc->sc_queue_len = TAIL_DROP_COUNT;
+
return 0;
bad3:
ieee80211_ifdetach(ic);
@@ -3507,6 +3882,9 @@
STAILQ_INIT(&bf_head);

if (SKB_CB(skb)->flags & M_RAW) {
+#ifdef JYD_FUNCTION_CALL_FREQUENCY
+ sc->sc_stats.ast_jyd_ath_hardstart_raw ++;
+#endif
bf = ath_take_txbuf(sc);
if (bf == NULL) {
/* All DMA buffers full, safe to try again. */
@@ -3543,9 +3921,12 @@
ATH_FF_MAGIC_CLR(skb);
an = ATH_NODE(ni);

+#ifdef JYD_FUNCTION_CALL_FREQUENCY
+ sc->sc_stats.ast_jyd_ath_hardstart ++;
+#endif
txq = sc->sc_ac2q[skb->priority];

- if (txq->axq_depth > TAIL_DROP_COUNT) {
+ if (txq->axq_depth > sc->sc_queue_len) {
/* Wish to reserve some DMA buffers, try again later. */
requeue = 1;
goto hardstart_fail;
@@ -3765,9 +4146,15 @@
netif_stop_queue(dev);
sc->sc_devstopped = 1;
/* Stop tracking again we are giving it back*/
+#ifdef JYD_FUNCTION_CALL_FREQUENCY
+ sc->sc_stats.ast_jyd_ath_hardstart_drop ++;
+#endif
ieee80211_skb_untrack(skb);
return NETDEV_TX_BUSY;
}
+#ifdef JYD_FUNCTION_CALL_FREQUENCY
+ sc->sc_stats.ast_jyd_ath_hardstart_silent_drop ++;
+#endif
/* Now free the SKBs */
ieee80211_dev_kfree_skb_list(&skb);
return NETDEV_TX_OK;
@@ -6973,6 +7360,47 @@
}
}

+ /* jyyoo (jaeyong): in-kernel-network-monitor */
+ /* information to put:
+ 1. interface queue occupation length
+ 2. retransmission count
+ 3. receiving error count
+ */
+ if( sc->sc_iknm_enable ) {
+ int next_head;
+ sk_buff_data_t network_header = skb->data + 24 /* sizeof wifi header */ + 8 /* sizeof llc */;
+ if( (*(unsigned char*)(network_header)) == 69 ) // it means IP header with header length 20
+ {
+ sc->dp_exchange_buffer_drop ++;
+ next_head = sc->sc_recv_monitor_head + 1;
+ if( next_head >= MAX_MPARAM ) next_head = next_head - MAX_MPARAM;
+
+ if( next_head == sc->sc_recv_monitor_tail ) // exchange buffer is full, just drop this packet
+ {
+ printk("monitoring packet dropped :%d\n", sc->dp_exchange_buffer_drop);
+ }
+ else // insert into the exchange buffer
+ {
+ int h = sc->sc_recv_monitor_head;
+ struct timeval tv;
+ do_gettimeofday(&tv);
+ sc->sc_recv_monitor_param[h].sec = tv.tv_sec;
+ sc->sc_recv_monitor_param[h].msec = tv.tv_usec;
+ memcpy( sc->sc_recv_monitor_param[h].header, skb->data, HEADER_LEN ); // 14 bytes for ethernet header
+ sc->sc_recv_monitor_head = next_head;
+ }
+
+ {
+ int h,t;
+ h = sc->sc_recv_monitor_head;
+ t = sc->sc_recv_monitor_tail;
+ if( h < t ) h += MAX_MPARAM;
+ if( (h-t) > MAX_MPARAM_PERPACKET && sc->sc_recv_kthread_send_alive )
+ wake_up_interruptible(&sc->sc_recv_queue_send);
+ }
+ }
+ }
+
/*
* Locate the node for sender, track state, and then
* pass the (referenced) node up to the 802.11 layer
@@ -8382,6 +8810,58 @@
try0, keyix, antenna, flags, ctsrate, ctsduration, icvlen, ivlen,
comp);

+ /* jyyoo (jaeyong): in-kernel-network-monitor */
+ /* information to put:
+ 1. interface queue occupation length
+ 2. retransmission count
+ 3. receiving error count
+ */
+ if( sc->sc_iknm_enable ) {
+ int next_head;
+
+ /* first check exchange buffe is full or not */
+ next_head = sc->sc_monitor_head + 1;
+ if( next_head >= MAX_MPARAM ) next_head = next_head - MAX_MPARAM;
+
+ if( next_head == sc->sc_monitor_tail ) // exchange buffer is full, just drop this packet
+ {
+ printk("IKNM: exchange buffer is full,,, packet dropped\n");
+ sc->dp_exchange_buffer_drop ++;
+ }
+ else // insert into the exchange buffer
+ {
+ int h = sc->sc_monitor_head;
+ struct timeval tv;
+ do_gettimeofday(&tv);
+ sc->sc_monitor_param[h].sec = tv.tv_sec;
+ sc->sc_monitor_param[h].msec = tv.tv_usec;
+ /* monitor 4 priority queues */
+ sc->sc_monitor_param[h].qlen[WME_AC_VO] = (u_int8_t)(sc->sc_ac2q[WME_AC_VO]->axq_depth);
+ sc->sc_monitor_param[h].qlen[WME_AC_VI] = (u_int8_t)(sc->sc_ac2q[WME_AC_VI]->axq_depth);
+ sc->sc_monitor_param[h].qlen[WME_AC_BE] = (u_int8_t)(sc->sc_ac2q[WME_AC_BE]->axq_depth);
+ sc->sc_monitor_param[h].qlen[WME_AC_BK] = (u_int8_t)(sc->sc_ac2q[WME_AC_BK]->axq_depth);
+ sc->sc_monitor_param[h].ret = (u_int8_t)sc->sc_stats.ast_tx_longretry + sc->sc_stats.ast_tx_shortretry;
+ sc->sc_monitor_param[h].err = (u_int8_t)sc->sc_stats.ast_rx_phyerr;
+ sc->sc_monitor_param[h].modRate = (u_int8_t)txrate;
+ if( skb->network_header )
+ memcpy( sc->sc_monitor_param[h].header, skb->data, HEADER_LEN ); // 14 bytes for ethernet header
+
+
+ sc->sc_monitor_head = next_head;
+ }
+
+ /* if the buffer is quite large, wake up the sending process */
+
+ {
+ int h,t;
+ h = sc->sc_monitor_head;
+ t = sc->sc_monitor_tail;
+ if( h < t ) h += MAX_MPARAM;
+ if( (h-t) > MAX_MPARAM_PERPACKET && sc->sc_kthread_send_alive )
+ wake_up_interruptible(&sc->sc_queue_send);
+ }
+ }
+
/*
* Formulate first tx descriptor with tx controls.
*/
@@ -10886,6 +11366,137 @@

ATH_LOCK(sc);
switch (cmd) {
+
+ /* jyyoo add to enable TTL-based packet filtering */
+ /* it is a part of work around solution for click output packet filtering */
+ case SIOCGTTLPACKETFILTER:
+ {
+ if( copy_to_user(ifr->ifr_data, &ic->ic_enable_ttl_pf, sizeof(ic->ic_enable_ttl_pf)))
+ {
+ printk("madwifi: siocgttlpacketfilter failed\n");
+ error = -EFAULT;
+ }
+ else
+ {
+ printk("read ttl packet filter : %d\n", ic->ic_enable_ttl_pf);
+ error = 0;
+ }
+ }
+ break;
+ case SIOCSTTLPACKETFILTER:
+ {
+ unsigned char buf [4];
+ if( copy_from_user( buf, ifr->ifr_data, sizeof(buf)))
+ {
+ printk("madwifi: siocsttlpacketfilter failed\n");
+ error = -EFAULT;
+ }
+ else
+ {
+ ic->ic_enable_ttl_pf = *((u_int32_t*)buf);
+ printk("set ttl packet filter : %d\n", ic->ic_enable_ttl_pf);
+ error = 0;
+ }
+ }
+ break;
+ /* jyyoo finish */
+
+ /* jyyoo add to enable adhoc edca */
+ case SIOCGADHOCEDCA:
+ {
+ if( copy_to_user(ifr->ifr_data, &ic->ic_adhoc_edca, sizeof(ic->ic_adhoc_edca)))
+ {
+ printk("madwifi: siocgadhocedca failed\n");
+ error = -EFAULT;
+ }
+ else
+ {
+ printk("read adhoc edca : %d\n", ic->ic_adhoc_edca);
+ error = 0;
+ }
+ }
+ break;
+ case SIOCSADHOCEDCA:
+ {
+ unsigned char buf [4];
+ if( copy_from_user( buf, ifr->ifr_data, sizeof(buf)))
+ {
+ printk("madwifi: siocsadhocedca failed\n");
+ error = -EFAULT;
+ }
+ else
+ {
+ ic->ic_adhoc_edca = *((u_int32_t*)buf);
+ printk("set adhoc edca : %d\n", ic->ic_adhoc_edca);
+ error = 0;
+ }
+ }
+ break;
+ /* jyyoo finish */
+ /* jyyoo (jaeyong) control iknm enable disable */
+ case SIOCGATHIKNM:
+ {
+ if( copy_to_user(ifr->ifr_data, &sc->sc_iknm_enable, sizeof(sc->sc_iknm_enable)))
+ {
+ printk("madwifi: siocathiknm failed\n");
+ error = -EFAULT;
+ }
+ else
+ {
+ printk("madwifi: siocathiknm succeed : %d\n", sc->sc_iknm_enable);
+ error = 0;
+ }
+ }
+ break;
+ case SIOCSATHIKNM:
+ {
+ unsigned char buf[4];
+ if( copy_from_user( buf, ifr->ifr_data, sizeof(buf)))
+ {
+ printk("madwifi: siocsathiknm failed\n");
+ error = -EFAULT;
+ }
+ else
+ {
+ sc->sc_iknm_enable = *((int*)buf);
+ printk("set iknm enable: %d\n", sc->sc_iknm_enable );
+ error = 0;
+ }
+ }
+ break;
+ /* jyyoo (jaeyong) control tx queue len */
+ case SIOCGATHBUFLEN:
+ {
+ if( copy_to_user(ifr->ifr_data, &sc->sc_queue_len, sizeof(sc->sc_queue_len)))
+ {
+ printk("madwifi: siocgathbuflen failed\n");
+ error = -EFAULT;
+ }
+ else
+ {
+ printk("read athbuflen : %d\n", sc->sc_queue_len);
+ error = 0;
+ }
+ }
+ break;
+ case SIOCSATHBUFLEN:
+ {
+ unsigned char buf [4];
+ if( copy_from_user( buf, ifr->ifr_data, sizeof(buf)))
+ {
+ printk("madwifi: siocsathbuflen failed\n");
+ error = -EFAULT;
+ }
+ else
+ {
+ sc->sc_queue_len = *((int*)buf);
+ printk("set athbuflen : %d\n", sc->sc_queue_len);
+ error = 0;
+ }
+ }
+ break;
+
+
case SIOCGATHSTATS:
sc->sc_stats.ast_tx_packets = sc->sc_devstats.tx_packets;
sc->sc_stats.ast_rx_packets = sc->sc_devstats.rx_packets;
diff -Nru madwifi-original/ath/if_athioctl.h madwifi-new/ath/if_athioctl.h
--- madwifi-original/ath/if_athioctl.h 2009-10-05 17:25:39.000000000 +0200
+++ madwifi-new/ath/if_athioctl.h 2009-10-15 12:37:56.000000000 +0200
@@ -42,6 +42,8 @@
#ifndef _DEV_ATH_ATHIOCTL_H
#define _DEV_ATH_ATHIOCTL_H

+#define JYD_FUNCTION_CALL_FREQUENCY
+
struct ath_stats {
u_int32_t ast_watchdog; /* device reset by watchdog */
u_int32_t ast_hardware; /* fatal hardware error interrupts */
@@ -98,6 +100,17 @@
u_int32_t ast_ant_txswitch; /* tx antenna switches */
u_int32_t ast_ant_rx[8]; /* rx frames with antenna */
u_int32_t ast_ant_tx[8]; /* tx frames with antenna */
+
+#ifdef JYD_FUNCTION_CALL_FREQUENCY
+ /* jyyoo add to debug function call frequencies */
+ u_int32_t ast_jyd_ath_hardstart;
+ u_int32_t ast_jyd_ath_hardstart_drop;
+ u_int32_t ast_jyd_ath_hardstart_silent_drop;
+ u_int32_t ast_jyd_ath_hardstart_raw;
+ u_int32_t ast_jyd_ieee80211_hardstart;
+ u_int32_t ast_jyd_ieee80211_hardstart_drop;
+ u_int32_t ast_jyd_ieee80211_hardstart_silent_drop;
+#endif
};

struct ath_diag {
@@ -120,6 +133,22 @@
#define SIOCGATHSTATS (SIOCDEVPRIVATE+0)
#define SIOCGATHDIAG (SIOCDEVPRIVATE+1)
#define SIOCGATHRADARSIG (SIOCDEVPRIVATE+2)
+// jyyoo : buffer len
+#define SIOCSATHBUFLEN (SIOCDEVPRIVATE+3)
+#define SIOCGATHBUFLEN (SIOCDEVPRIVATE+4)
+// jyyoo : in kernel network monitoring
+#define SIOCSATHIKNM (SIOCDEVPRIVATE+5)
+#define SIOCGATHIKNM (SIOCDEVPRIVATE+6)
+// jyyoo : add for per-flow monitoring
+#define SIOCGPFMS_SIGNAL (SIOCDEVPRIVATE+10)
+#define SIOCGPFMS (SIOCDEVPRIVATE+11)
+// jyyoo : add for TTL-based packet filtering
+#define SIOCSTTLPACKETFILTER (SIOCDEVPRIVATE+12)
+#define SIOCGTTLPACKETFILTER (SIOCDEVPRIVATE+13)
+// jyyoo : add for adhoc edca
+#define SIOCSADHOCEDCA (SIOCDEVPRIVATE+14)
+#define SIOCGADHOCEDCA (SIOCDEVPRIVATE+15)
+
#else
#define SIOCGATHSTATS _IOWR('i', 137, struct ifreq)
#define SIOCGATHDIAG _IOWR('i', 138, struct ath_diag)
diff -Nru madwifi-original/ath/if_athvar.h madwifi-new/ath/if_athvar.h
--- madwifi-original/ath/if_athvar.h 2009-10-05 17:25:39.000000000 +0200
+++ madwifi-new/ath/if_athvar.h 2009-10-15 12:37:28.000000000 +0200
@@ -47,9 +47,17 @@
#include "ah_os.h"
#include "if_athioctl.h"
#include
+#include
#include "net80211/ieee80211.h" /* XXX for WME_NUM_AC */
#include
#include
+#include /* for in_aton */
+#include
+#include
+#include
+#include
+#include
+
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)
# include
#endif
@@ -58,6 +66,7 @@
#define irqs_disabled() 0
#endif

+
/*
* Deduce if tasklets are available. If not then
* fall back to using the immediate work queue.
@@ -596,6 +605,34 @@
(_tqs)->axq_link = NULL; \
} while (0)

+
+/* jyyoo (jaeyong): in-kernel-network-monitoring */
+#define HEADER_LEN 76
+struct monitor_param {
+ int sec;
+ int msec;
+ u_int8_t qlen[4];
+ u_int8_t ret;
+ u_int8_t err;
+ u_int8_t modRate;
+ u_int8_t reserved;
+ char header[HEADER_LEN]; /* including ethernet, ip, tcp (+option) header */
+};
+/* MAX_MPARAM basically determines the tradeoff between cpu efficiency and memory efficiency */
+#define HEADER_LEN 76
+struct monitor_param_recv {
+ int sec;
+ int msec;
+ char header[HEADER_LEN]; /* including ethernet, ip, tcp (+option) header */
+};
+/* MAX_MPARAM basically determines the tradeoff between cpu efficiency and memory efficiency */
+/* we use 8KB as the buffer for exchanging the header from process context of outgoing packet and kernel thread */
+/* 8192 / 92 = 85 */
+#define MAX_MPARAM 85
+/* 1440 / 92 = 15 */
+#define MAX_MPARAM_PERPACKET 15
+
+
/*
* concat buffers from one queue to other
*/
@@ -839,6 +876,59 @@
* detected radars */
u_int32_t sc_nexttbtt;
u_int64_t sc_last_tsf;
+
+ /* jyyoo (jaeyong): in-kernel-network-monitor */
+ struct socket* sc_recv_sock_mclient; /* monitor client */
+ int sc_recv_port_number; /* server port */
+ struct sockaddr_in sc_recv_serv_addr; /* server ip address */
+ struct iovec sc_recv_iov_msg; /* message structure */
+ struct msghdr sc_recv_msghdr; /* message header structure */
+ char sc_recv_msgbuf[1440];
+
+ struct sockaddr_in sc_recv_serv_addr2; /* server ip address */
+
+ /* kernel thread for sending the network info to server */
+ struct task_struct* sc_recv_kthread_send;
+ wait_queue_head_t sc_recv_queue_send;
+ int sc_recv_kthread_send_alive;
+
+ /* buffer for sharing between kernel thread and the process of outgoing packet */
+ struct monitor_param_recv sc_recv_monitor_param[MAX_MPARAM];
+ int sc_recv_monitor_head;
+ int sc_recv_monitor_tail;
+
+ spinlock_t sc_recv_send_lock;
+ /* jyyoo (jaeyong): in-kernel-network-monitor */
+ struct socket* sc_sock_mclient; /* monitor client */
+ int sc_port_number; /* server port */
+ struct sockaddr_in sc_serv_addr; /* server ip address */
+ struct iovec sc_iov_msg; /* message structure */
+ struct msghdr sc_msghdr; /* message header structure */
+ char sc_msgbuf[1440];
+
+ struct sockaddr_in sc_serv_addr2; /* server ip address */
+
+ /* kernel thread for sending the network info to server */
+ struct task_struct* sc_kthread_send;
+ wait_queue_head_t sc_queue_send;
+ int sc_kthread_send_alive;
+
+ /* buffer for sharing between kernel thread and the process of outgoing packet */
+ struct monitor_param sc_monitor_param[MAX_MPARAM];
+ int sc_monitor_head;
+ int sc_monitor_tail;
+
+ spinlock_t sc_send_lock;
+
+ /* jyyoo (jaeyong): control tx queue len */
+ int sc_queue_len;
+
+ /* debugging param */
+ int dp_exchange_buffer_drop;
+
+ /* in-kernel-network-monitor enable/disable toggle */
+ int sc_iknm_enable;
+
};

typedef void (*ath_callback) (struct ath_softc *);
diff -Nru madwifi-original/net80211/ieee80211_output.c madwifi-new/net80211/ieee80211_output.c
--- madwifi-original/net80211/ieee80211_output.c 2009-10-05 17:25:39.000000000 +0200
+++ madwifi-new/net80211/ieee80211_output.c 2009-10-16 23:23:00.000000000 +0200
@@ -53,6 +53,8 @@
#include "if_ethersubr.h"
#include "if_media.h"

+#include
+
#include
#include
#include
@@ -84,13 +86,22 @@
{
struct ieee80211vap *vap = ni->ni_vap;
struct ether_header *eh = (struct ether_header *) skb->data;
+ struct ieee80211com *ic = ni->ni_ic;
int v_wme_ac = 0, d_wme_ac = 0;

/* default priority */
skb->priority = WME_AC_BE;

- if (!(ni->ni_flags & IEEE80211_NODE_QOS))
- return 0;
+ /* jyyoo add to enable ad-hoc edca */
+
+ if( !ic->ic_adhoc_edca )
+ {
+ if (!(ni->ni_flags & IEEE80211_NODE_QOS))
+ return 0;
+ }
+
+ /* jyyoo end */
+

/*
* If node has a vlan tag then all traffic
@@ -111,7 +122,8 @@
ni->ni_stats.ns_tx_vlanmismatch++;
return 1;
}
- if (ni->ni_flags & IEEE80211_NODE_QOS) {
+ if (ni->ni_flags & IEEE80211_NODE_QOS || ic->ic_adhoc_edca) {
+
v_pri = (tag >> VLAN_PRI_SHIFT) & VLAN_PRI_MASK;
switch (v_pri) {
case 1:
@@ -206,6 +218,7 @@
struct net_device *parent = ic->ic_dev;
struct ieee80211_node *ni = NULL;
struct ether_header *eh;
+ int re=0;

/* reset the skb of new frames reaching this layer BEFORE
* we invoke ieee80211_skb_track. */
@@ -230,10 +243,43 @@
#endif
goto bad;
}
+
+#ifdef JYD_FUNCTION_CALL_FREQUENCY
+ /* jyyoo to debug function call frequencies */
+ {
+ struct net_device* parent_dev = vap->iv_ic->ic_dev;
+ struct ath_softc* sc = parent_dev->priv;
+ sc->sc_stats.ast_jyd_ieee80211_hardstart ++;
+ }
+#endif
+
+ /*
+ * jyyoo : hack to support click
+ * desc: click user-level do not filter the local output packet properly
+ * because iptables can not filter the local output
+ * appropriately. if we use iptables to filter the local
+ * ouput packet, then all the click packets are also filtered out.
+ * The trick is as follows:
+ * ip uses default ttl as IPDEFTTL (64). We filter out ttl of IPDEFTTL (64)
+ * and use pass packets with ttl IPDEFTTL -1 (63). the local packet of ttl IPDEFTTL (64)
+ * will be filtered and we can manually decrease the ttl.
+ */
+ if( ic->ic_enable_ttl_pf )
+ {
+ const struct iphdr *ip = (struct iphdr *)
+ (skb->data + sizeof (struct ether_header));
+ if( ip->version == IPVERSION && ip->ttl == IPDEFTTL )
+ {
+ printk("JYD: packet filtered\n");
+ goto bad;
+ }
+ }
+ /* jyyoo finish */
+

if (vap->iv_opmode == IEEE80211_M_MONITOR) {
ieee80211_monitor_encap(vap, skb);
- ieee80211_parent_queue_xmit(skb);
+ re = ieee80211_parent_queue_xmit(skb);
return NETDEV_TX_OK;
}

@@ -296,15 +342,50 @@
SKB_CB(skb1)->ni = ieee80211_find_txnode(vap->iv_xrvap,
eh->ether_dhost);
/* Ignore this return code. */
- ieee80211_parent_queue_xmit(skb1);
+ re = ieee80211_parent_queue_xmit(skb1);
}
}
#endif
ieee80211_unref_node(&ni);
- ieee80211_parent_queue_xmit(skb);
+ re = ieee80211_parent_queue_xmit(skb);
+
+ if( re == 1 )
+ {
+#ifdef JYD_FUNCTION_CALL_FREQUENCY
+ /* jyyoo to debug function call frequencies */
+ {
+ struct net_device* parent_dev = vap->iv_ic->ic_dev;
+ struct ath_softc* sc = parent_dev->priv;
+ sc->sc_stats.ast_jyd_ieee80211_hardstart_drop ++;
+ }
+#endif
+
+ /* jyyoo : note
+ * to make the complete driver, we have to stop
+ * queue a bit and wake when it is avilable,
+ * currently, not figured when we have to wake
+ * the queue (netif_wake_queue).
+ * It is probably related when ath(wifi0)-buffer
+ * is sufficiently drained out
+ */
+ // netif_stop_queue(dev);
+
+ //return NETDEV_TX_BUSY;
+ // ENOUBUFS will be directly delivered to raw socket send function
+ return -ENOBUFS;
+ }
return NETDEV_TX_OK;

bad:
+#ifdef JYD_FUNCTION_CALL_FREQUENCY
+ /* jyyoo to debug function call frequencies */
+ {
+ struct net_device* parent_dev = vap->iv_ic->ic_dev;
+ struct ath_softc* sc = parent_dev->priv;
+ sc->sc_stats.ast_jyd_ieee80211_hardstart_silent_drop ++;
+ }
+#endif
+
if (skb != NULL)
ieee80211_dev_kfree_skb(&skb);
if (ni != NULL)
@@ -316,8 +397,9 @@
* skb is consumed in all cases
*/

-void ieee80211_parent_queue_xmit(struct sk_buff *skb) {
+int ieee80211_parent_queue_xmit(struct sk_buff *skb) {
struct ieee80211vap *vap = skb->dev->priv;
+ int re=0;

vap->iv_devstats.tx_packets++;
vap->iv_devstats.tx_bytes += skb->len;
@@ -327,9 +409,18 @@
skb->dev = vap->iv_ic->ic_dev;

if (netif_queue_stopped(skb->dev))
- ieee80211_dev_kfree_skb(&skb);
+ {
+ vap->iv_devstats.tx_dropped++;
+ re=1;
+// ieee80211_dev_kfree_skb(&skb); // jyyoo disabled the code
+ ieee80211_skb_untrack(skb);
+ }
else if (dev_queue_xmit(skb) == NET_XMIT_DROP)
+ {
vap->iv_devstats.tx_dropped++;
+ re=1;
+ }
+ return re;
}

/*
diff -Nru madwifi-original/net80211/ieee80211_proto.h madwifi-new/net80211/ieee80211_proto.h
--- madwifi-original/net80211/ieee80211_proto.h 2009-10-05 17:25:39.000000000 +0200
+++ madwifi-new/net80211/ieee80211_proto.h 2009-10-14 20:17:08.000000000 +0200
@@ -73,7 +73,7 @@
struct sk_buff *, int, int, u_int64_t);
void ieee80211_sta_pwrsave(struct ieee80211vap *, int);
int ieee80211_hardstart(struct sk_buff *, struct net_device *);
-void ieee80211_parent_queue_xmit(struct sk_buff *);
+int ieee80211_parent_queue_xmit(struct sk_buff *); // jyyoo modify
int ieee80211_send_nulldata(struct ieee80211_node *);
int ieee80211_send_qosnulldata(struct ieee80211_node *, int);
int ieee80211_send_mgmt(struct ieee80211_node *, int, int);
diff -Nru madwifi-original/net80211/ieee80211_var.h madwifi-new/net80211/ieee80211_var.h
--- madwifi-original/net80211/ieee80211_var.h 2009-10-05 17:25:39.000000000 +0200
+++ madwifi-new/net80211/ieee80211_var.h 2009-10-05 19:48:35.000000000 +0200
@@ -450,6 +450,15 @@
u_int8_t ic_chanchange_tbtt;
u_int8_t ic_chanchange_chan;

+
+ /* jyyoo add: enable to DEFTTL filtering to support user-level click
+ * to be able to filter out the original kernel-generated packets
+ */
+ u_int32_t ic_enable_ttl_pf;
+
+ /* jyyoo add: enable adhoc edca */
+ u_int32_t ic_adhoc_edca;
+
/* Global debug flags applicable to all VAPs */
int ic_debug;
/* used for reference tracking/counting. Nodes are shared between VAPs,
diff -Nru madwifi-original/tools/athstats.c madwifi-new/tools/athstats.c
--- madwifi-original/tools/athstats.c 2009-10-05 17:25:39.000000000 +0200
+++ madwifi-new/tools/athstats.c 2009-10-15 12:46:31.000000000 +0200
@@ -279,6 +279,17 @@
"phyerr",
"rssi",
"rate");
+#ifdef JYD_FUNCTION_CALL_FREQUENCY
+ printf(" %8s %8s %8s %8s %8s %8s %8s",
+ "athxmit",
+ "athraw",
+ "athdrop",
+ "athsdrop",
+ "netxmit",
+ "netdrop",
+ "netsdrop"
+ );
+#endif
putchar('\n');
fflush(stdout);
line = 0;
@@ -290,7 +301,7 @@
err(1, ifr.ifr_name);
if (!getifstats(ifr.ifr_name, &icur, &ocur))
err(1, ifr.ifr_name);
- printf("%8lu %8lu %7u %7u %7u %6u %6u %6u %7u %4u %3uM\n",
+ printf("%8lu %8lu %7u %7u %7u %6u %6u %6u %7u %4u %3uM",
(icur - itot) -
(cur.ast_rx_mgt - total.ast_rx_mgt),
ocur - otot,
@@ -303,6 +314,19 @@
cur.ast_rx_phyerr - total.ast_rx_phyerr,
cur.ast_rx_rssi,
rate);
+
+#ifdef JYD_FUNCTION_CALL_FREQUENCY
+ printf("%8lu %8lu %8lu %8lu %8lu %8lu %8lu",
+ cur.ast_jyd_ath_hardstart - total.ast_jyd_ath_hardstart,
+ cur.ast_jyd_ath_hardstart_raw - total.ast_jyd_ath_hardstart_raw,
+ cur.ast_jyd_ath_hardstart_drop - total.ast_jyd_ath_hardstart_drop,
+ cur.ast_jyd_ath_hardstart_silent_drop - total.ast_jyd_ath_hardstart_silent_drop,
+ cur.ast_jyd_ieee80211_hardstart - total.ast_jyd_ieee80211_hardstart,
+ cur.ast_jyd_ieee80211_hardstart_drop - total.ast_jyd_ieee80211_hardstart_drop,
+ cur.ast_jyd_ieee80211_hardstart_silent_drop - total.ast_jyd_ieee80211_hardstart_silent_drop );
+#endif
+
+ printf("\n");
total = cur;
itot = icur;
otot = ocur;
diff -Nru madwifi-original/tools/wlanconfig.c madwifi-new/tools/wlanconfig.c
--- madwifi-original/tools/wlanconfig.c 2009-10-05 17:25:39.000000000 +0200
+++ madwifi-new/tools/wlanconfig.c 2009-10-05 19:54:01.000000000 +0200
@@ -61,6 +61,7 @@
#include "net80211/ieee80211.h"
#include "net80211/ieee80211_crypto.h"
#include "net80211/ieee80211_ioctl.h"
+#include "ath/if_athioctl.h"
#include "do_multi.h"

/*
@@ -201,6 +202,91 @@
err(1, "unknown 'list' option: %s", arg);
} else /* NB: for compatibility */
list_stations(ifname);
+ /* jyyoo (jaeyong) tx queue len control */
+ } else if ( streq(cmd, "command")) {
+ if( argc == 5 )
+ {
+ struct ifreq ifr;
+ int s;
+ s = socket(AF_INET, SOCK_DGRAM, 0);
+ if( s < 0 )
+ err(1, "socket");
+ ifname = argv[1];
+ strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+ if( streq(argv[3], "stxqlen"))
+ {
+ int value=atoi(argv[4]);
+ ifr.ifr_data = (caddr_t) &value;
+ if( ioctl(s, SIOCSATHBUFLEN, &ifr) < 0 )
+ err(1, ifr.ifr_name);
+ } else if( streq(argv[3], "setiknm"))
+ {
+ int value=atoi(argv[4]);
+ ifr.ifr_data = (caddr_t) &value;
+ if( ioctl(s, SIOCSATHIKNM, &ifr) < 0 )
+ err(1, ifr.ifr_name);
+ }
+ else if (streq(argv[3], "sttlpf"))
+ {
+ int value=atoi(argv[4]);
+ ifr.ifr_data = (caddr_t) &value;
+ if( ioctl(s, SIOCSTTLPACKETFILTER, &ifr) < 0 )
+ err(1, ifr.ifr_name);
+ }
+ else if (streq(argv[3], "sadhocedca"))
+ {
+ int value=atoi(argv[4]);
+ ifr.ifr_data = (caddr_t) &value;
+ if( ioctl(s, SIOCSADHOCEDCA, &ifr) < 0 )
+ err(1, ifr.ifr_name);
+ }
+ close(s);
+ }
+ else if( argc == 4 )
+ {
+ struct ifreq ifr;
+ int s;
+ s = socket(AF_INET, SOCK_DGRAM, 0);
+ if( s < 0 )
+ err(1, "socket");
+ ifname = argv[1];
+ strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+ if( streq(argv[3], "gtxqlen"))
+ {
+ int value;
+ ifr.ifr_data = (caddr_t) &value;
+ if( ioctl(s, SIOCGATHBUFLEN, &ifr) < 0 )
+ err(1, ifr.ifr_name);
+ printf("queue len: %d\n", value);
+ } else if( streq(argv[3], "getiknm"))
+ {
+ int value;
+ ifr.ifr_data = (caddr_t) &value;
+ if( ioctl(s, SIOCGATHIKNM, &ifr) < 0 )
+ err(1, ifr.ifr_name);
+ printf("iknm : %d\n", value);
+ }
+ if( streq(argv[3], "gttlpf"))
+ {
+ int value;
+ ifr.ifr_data = (caddr_t) &value;
+ if( ioctl(s, SIOCGTTLPACKETFILTER, &ifr) < 0 )
+ err(1, ifr.ifr_name);
+ printf("ttl packet filter mode: %d\n", value);
+ }
+ if( streq(argv[3], "gadhocedca"))
+ {
+ int value;
+ ifr.ifr_data = (caddr_t) &value;
+ if( ioctl(s, SIOCGADHOCEDCA, &ifr) < 0 )
+ err(1, ifr.ifr_name);
+ printf("adhoc edca: %d\n", value);
+ }
+
+ close(s);
+
+ }
+
} else
usage();

@@ -288,6 +374,7 @@
fprintf(stderr, " wlanmode [sta|adhoc|ap|monitor|wds|ahdemo] [bssid | -bssid] [nosbeacon]\n");
fprintf(stderr, "usage: wlanconfig athX destroy\n");
fprintf(stderr, "usage: wlanconfig athX list [active|ap|caps|chan|freq|keys|scan|sta|wme]\n");
+ fprintf(stderr, "usage: wlanconfig wifiX command [ [s|g]ttlpf | [s|g]adhocedca ]\n");
exit(-1);
}

No comments:

Post a Comment