All of lore.kernel.org
 help / color / mirror / Atom feed
* proposal of xt_physdev's patch to limit traffic
@ 2010-10-21 10:27 ahmed amamou
  2010-10-21 10:47 ` Gianni Tedesco
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: ahmed amamou @ 2010-10-21 10:27 UTC (permalink / raw)
  To: xen-devel


[-- Attachment #1.1: Type: text/plain, Size: 1024 bytes --]


Good morning every Body

I'm new in modules programming and I've made a patch to limit packet traffic in bridge(patch is joined with the mail).

In order to limit the traffic, i used the netback limitation method to count traffic with skb->len  for each vif to stop traffic, as i can't put down vif, i change the hotdrop flag to 1 (change was based on xt_physdev of dom 0 2.6.18.8 so  in the patch will find it 1 but it's easy to change the patch to recent dom 0 version by just changing  *hotdrop=1; to *par->hotdrop=true;)

The problem that i have is that when i reach traffic limit (30mb/s by defaut and can be changed via proc EX: "echo vif1.0 312500,50000' >/proc/changeRXrate know that doing it via proc is the worst way but i don't know any other way to do it any suggestion will be welcome ) and begin drop traffic fell terribly and became 10mb/s

will be really thankful if anybody could help me with suggestions and advices in order to  solve this problem 


Sincerly 

Ahmed AMAMOU 

 		 	   		  

[-- Attachment #1.2: Type: text/html, Size: 1280 bytes --]

[-- Attachment #2: xt_physdev_diff --]
[-- Type: application/octet-stream, Size: 10846 bytes --]

*** xt_physdev_old.c	2010-10-18 10:53:54.000000000 +0200
--- xt_physdev.c	2010-10-21 11:17:47.000000000 +0200
***************
*** 14,21 ****
--- 14,31 ----
  #include <linux/netfilter/xt_physdev.h>
  #include <linux/netfilter/x_tables.h>
  #include <linux/netfilter_bridge.h>
+ #include <linux/string.h>
+ 
+ #include <linux/slab.h> /* For kmalloc() */
+ #include <linux/timer.h>
+ #include <linux/sched.h>
+ #include <linux/proc_fs.h>
+ #include <linux/vmalloc.h>
  #define MATCH   1
  #define NOMATCH 0
+ #ifndef ULONG_MAX
+ #define ULONG_MAX	(~0UL)
+ #endif 
  
  MODULE_LICENSE("GPL");
  MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>");
***************
*** 23,28 ****
--- 33,316 ----
  MODULE_ALIAS("ipt_physdev");
  MODULE_ALIAS("ip6t_physdev");
  
+ #define DEFAULT_CREDIT_BYTES 187500
+ #define DEFAULT_CREDIT_USEC 50000 
+ #define PROC_ENTRY_FILENAME "changeRXrate"
+ #define INTERFACENAMESIZE 10
+ #define LONGSIZE 64
+ #define PROCFS_MAX_SIZE 1024
+ 
+ struct interface_limit{
+         char name[IFNAMSIZ];
+ 	unsigned long credit_bytes;
+ 	unsigned long credit_usec;
+ 	unsigned long remaining_credit;
+ 	unsigned long credit_timeout;
+ 	struct interface_limit *next;
+ };
+ 
+ static char procfs_buffer[PROCFS_MAX_SIZE];
+ static unsigned long procfs_buffer_size = 0;
+ struct proc_dir_entry *Proc_File;
+ static struct interface_limit* interface_list=NULL;
+ 
+ 
+ /**
+ mystrtoul convert char to unsigned long 
+ @param str
+ @return unsigned long 
+ **/
+ unsigned long
+ mystrtoul(char *str )
+ {
+   unsigned long res;
+   unsigned long mul;
+   char *ptr;
+   mul = 1;
+   res=0;
+   for(ptr = str + strlen(str) - 1; ptr >= str; ptr--){ 
+     if(*ptr < '0' || *ptr > '9') 
+       return(-1);
+     res += (*ptr - '0') * mul;
+     mul *= 10;
+   }
+   return res;
+ }
+ /**
+ initialise_interface_list initilize the interface_list by adding the first interface 
+ @param name first interface name 
+ @param credit_byte first interface credit_byte
+ @param credit_usec first interface cedti_usec
+ @return  the first added interface 
+ **/
+ struct interface_limit*
+ initialize_interface_list(char* name, unsigned long credit_bytes,unsigned long credit_usec)
+ {
+   interface_list=kmalloc(sizeof(struct interface_limit),GFP_KERNEL);
+   sprintf(interface_list->name,"%s",name);
+   if (credit_bytes > 0)
+     interface_list->credit_bytes=credit_bytes;
+   else
+     interface_list->credit_bytes=DEFAULT_CREDIT_BYTES;
+   if (credit_usec > 0)
+     interface_list->credit_usec=credit_usec;
+   else
+     interface_list->credit_usec=DEFAULT_CREDIT_USEC;
+   interface_list->remaining_credit=0;
+   interface_list->credit_timeout=jiffies;
+   interface_list->next=NULL;
+ return interface_list;
+ 
+ }
+ 
+ /**
+ add_interface add interface to our interface list 
+ @param name added interface name 
+ @param credit_byte added interface credit_byte
+ @param credit_usec added interface cedti_usec
+ @return  the added interface 
+ **/
+ struct interface_limit*
+ add_interface(char* name, unsigned long  credit_bytes,unsigned long  credit_usec)
+ {
+   struct interface_limit * new_interface=NULL;
+   new_interface=kmalloc(sizeof(struct interface_limit),GFP_KERNEL);
+   sprintf(new_interface->name,"%s",name);
+   if (credit_bytes > 0)
+     new_interface->credit_bytes=credit_bytes;
+   else
+     new_interface->credit_bytes=DEFAULT_CREDIT_BYTES;
+   if (credit_usec > 0)
+     new_interface->credit_usec=credit_usec;
+   else
+     new_interface->credit_usec=DEFAULT_CREDIT_USEC;
+   new_interface->remaining_credit=0;
+   new_interface->credit_timeout=jiffies;
+   new_interface->next=interface_list->next;
+   interface_list->next=new_interface;
+ return new_interface;
+ }
+ 
+ /**
+ add_interface_credit refill interface credit
+ @param netif network interface that w'll refill with credit byte
+ @return 0 if success 
+ **/
+ static int 
+ add_interface_credit(struct interface_limit * netif)
+ {
+   unsigned long max_burst, max_credit;
+   max_burst = 3*netif->credit_bytes;
+   max_credit = netif->remaining_credit + netif->credit_bytes;
+   if (max_credit < netif->remaining_credit)
+     max_credit = ULONG_MAX;
+   netif->remaining_credit = min(max_credit, max_burst);
+   //printk(KERN_ALERT "remaining_credit after add: %lu\n",netif->remaining_credit);
+   return 0;
+ }
+ 
+ 
+ 
+ /**
+ find_interface_by_name
+ @param name the name of serached interface
+ @return pointer to the interface 
+ **/
+ 
+ struct interface_limit* 
+ find_interface_by_name(char* name)
+ {
+   if (interface_list != NULL){
+     struct interface_limit* nextpos=interface_list->next;
+     if (!(strcmp(interface_list->name,name)))
+       return interface_list;
+     else {
+       while (nextpos !=NULL){
+ 	if (!(strcmp(nextpos->name,name)))
+ 	  return nextpos;
+ 	nextpos=nextpos->next;
+       }
+       return add_interface(name,0,0);
+     }
+   } else {
+     return initialize_interface_list(name,0,0);
+   }
+ }
+ 
+ /**
+ check if the network interface that will recive the paquet is allowed to recive it and check for credit add  
+ @param netif_name interface that will check for credit
+ @param Rxrequestsize size of resived paquet to match
+ @return 1 if have enough credit 0 else  
+ **/
+ 
+ 
+ static int 
+ check_remaining_credit(char* netif_name,unsigned long Rxrequestsize)
+ {
+ 
+   int ret;
+   unsigned long next_credit;
+   unsigned long now;   
+   struct interface_limit * netif=NULL;
+   netif=find_interface_by_name(netif_name);
+   ret=0;
+     
+   now = jiffies;
+   next_credit =netif->credit_timeout + msecs_to_jiffies(netif->credit_usec / 1000);//next credit satrting time 
+ 
+   //if (time_after_eq(now, next_credit)){   // we started a new slice so w'll have to refill credit 
+   if (now >= next_credit){ // we started a new slice so w'll have to refill credit
+     netif->credit_timeout = now;
+     add_interface_credit(netif);
+     //printk(KERN_ALERT "now: %lu next_credit: %lu\n",now,next_credit);
+   }
+   //printk(KERN_ALERT "ifname :%s Rxrequestsize: %lu remaining_credit: %lu\n",netif->name,Rxrequestsize,netif->remaining_credit);
+   if (netif->remaining_credit > Rxrequestsize){
+     //printk(KERN_ALERT "%s match\n",netif->name);
+     netif->remaining_credit -= Rxrequestsize;
+     return 1;
+   } else{
+     //printk(KERN_ALERT "%s no match\n",netif->name);
+     return 0;
+   }
+   return 1;
+ }
+ 
+ 
+ int 
+ procfile_read(char *buffer,
+ 	      char **buffer_location,
+ 	      off_t offset, int buffer_length, int *eof, void *data)
+ {
+ int l;
+ int len;
+ int i=0;
+ off_t   begin = 0;
+ 
+   if (offset > 0){
+     len  = 0;
+   }else{
+     if (interface_list!=NULL)
+     {
+       struct interface_limit* nextpos=interface_list->next;
+       len= sprintf(buffer,"%i ifname=%s bytes=%lu usec=%lu\n",i,interface_list->name,interface_list->credit_bytes,interface_list->credit_usec);
+       i += 1;
+       while (nextpos !=NULL){
+ 	  l=sprintf(buffer+len,"%i ifname=%s bytes=%lu usec=%lu\n",i,nextpos->name,nextpos->credit_bytes,nextpos->credit_usec);
+ 	  len += l;
+ 	  i += 1;
+ 	  nextpos=nextpos->next;
+ 	  if (len+begin > offset+buffer_length)
+                         goto done;
+           if (len+begin < offset) {
+                         begin += len;
+                         len = 0;
+ 	  }
+       }
+     } else {
+       len=sprintf(buffer,"no interface detected for the moment\n");
+       return len;
+ 
+     }
+   }
+ 
+ done:
+         if (offset >= len+begin)
+                 return 0;
+         *buffer_location = buffer + (offset-begin);
+         return ((buffer_length < begin+len-offset) ? buffer_length : begin+len-offset);
+ }
+ 
+ int 
+ procfile_write(struct file *file, const char *buffer, unsigned long count,
+ 		   void *data)
+ {
+   int i=0;
+   int j=0;
+   char name[INTERFACENAMESIZE];
+   char rate[LONGSIZE];
+   char slice[LONGSIZE];
+   struct interface_limit * tmp_intrface=NULL;
+   
+   procfs_buffer_size = count;
+   if (procfs_buffer_size > PROCFS_MAX_SIZE ) {
+ 		procfs_buffer_size = PROCFS_MAX_SIZE;
+   }
+ 
+   /* write data to the buffer */
+   if ( copy_from_user(procfs_buffer, buffer, procfs_buffer_size) ) {
+ 	return -EFAULT;
+   }
+   
+   while (procfs_buffer[i]!= ' ' && i< count){
+   name[i]=procfs_buffer[i];
+   i++;
+   }
+   name[i]='\0';
+   i++;
+   while(procfs_buffer[i]!= ',' && i< count){
+     rate[j]=procfs_buffer[i];
+     i++;
+     j++;
+   }
+         
+   rate[j]='\0';
+   i++;
+   j=0;
+   while(i< count){
+     slice[j]=procfs_buffer[i];
+     i++;
+     j++;
+   }
+   slice[j-1]='\0';
+   tmp_intrface= find_interface_by_name(name);
+   tmp_intrface->credit_bytes=mystrtoul(rate);
+   tmp_intrface->credit_usec=mystrtoul(slice);
+   return procfs_buffer_size;
+ 
+ }
+ 
  static int
  match(const struct sk_buff *skb,
        const struct net_device *in,
***************
*** 90,100 ****
  		return MATCH;
  	outdev = nf_bridge->physoutdev ?
  		 nf_bridge->physoutdev->name : nulldevname;
  	for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned int); i++) {
  		ret |= (((const unsigned int *)outdev)[i]
  			^ ((const unsigned int *)info->physoutdev)[i])
  			& ((const unsigned int *)info->out_mask)[i];
! 	}
  	return (ret != 0) ^ !(info->invert & XT_PHYSDEV_OP_OUT);
  }
  
--- 378,396 ----
  		return MATCH;
  	outdev = nf_bridge->physoutdev ?
  		 nf_bridge->physoutdev->name : nulldevname;
+ /*code modif in match */
+ 	if (outdev[0]=='v' || outdev[0]=='V'){
+ 	  if (!(check_remaining_credit(outdev,(unsigned long)skb->len))){
+ 	    *hotdrop=1; // *par->hotdrop=true; in recent kernel 
+ 	    return NOMATCH;
+ 	  }
+ 	}
+ /*code modif in match*/
  	for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned int); i++) {
  		ret |= (((const unsigned int *)outdev)[i]
  			^ ((const unsigned int *)info->physoutdev)[i])
  			& ((const unsigned int *)info->out_mask)[i];
! 	}	
  	return (ret != 0) ^ !(info->invert & XT_PHYSDEV_OP_OUT);
  }
  
***************
*** 150,155 ****
--- 446,465 ----
  static int __init xt_physdev_init(void)
  {
  	int ret;
+ 	Proc_File = create_proc_entry(PROC_ENTRY_FILENAME, 0644, NULL);
+ 	if (Proc_File == NULL) {
+ 		remove_proc_entry(PROC_ENTRY_FILENAME, &proc_root);
+ 		printk(KERN_ALERT "Error: Could not initialize /proc/%s\n",
+ 		       PROC_ENTRY_FILENAME);
+ 		return -ENOMEM;
+ 	}
+ 	Proc_File->write_proc = procfile_write;
+ 	Proc_File->read_proc = procfile_read;
+ 	Proc_File->owner = THIS_MODULE;
+ 	Proc_File->mode = S_IFREG | S_IRUGO;
+ 	Proc_File->uid = 0;
+ 	Proc_File->gid = 0;
+ 	Proc_File->size = 80;
  
  	ret = xt_register_match(&physdev_match);
  	if (ret < 0)
***************
*** 166,171 ****
--- 476,482 ----
  {
  	xt_unregister_match(&physdev_match);
  	xt_unregister_match(&physdev6_match);
+         remove_proc_entry(PROC_ENTRY_FILENAME, &proc_root);
  }
  
  module_init(xt_physdev_init);

[-- Attachment #3: Type: text/plain, Size: 138 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2010-10-21 12:38 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-10-21 10:27 proposal of xt_physdev's patch to limit traffic ahmed amamou
2010-10-21 10:47 ` Gianni Tedesco
2010-10-21 10:52 ` Ian Campbell
2010-10-21 12:38 ` Felix Kuperjans

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.