loadlwipv6 inlined
[vde.git] / vde-2 / vde_switch / packetq.c
blob16643a4aad32fc0027a42ac7757e449b9253ca82
1 /*
2 * packetq - packet queue management. try to send packets several times before discarding.
3 * Copyright 2005 Renzo Davoli
4 * Licensed under the GPLv2
5 */
7 #include <config.h>
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include <string.h>
11 #include <sys/time.h>
12 #include <time.h>
13 #include <sys/types.h>
14 #include <unistd.h>
15 #include <errno.h>
16 #include <syslog.h>
18 #include <consmgmt.h>
19 #include <vde.h>
21 #ifdef VDE_PQ
22 #include "packetq.h"
24 int packetq_timeout= -1;
25 static int countq;
26 #define TIMEOUT 5
27 #define TIMES 10
28 #define MAXQLEN 4192
30 struct packetqq {
31 int (*sender)(int fd, int fd_ctl, void *packet, int len, void *data, int port);
32 int fd;
33 int fd_ctl;
34 void *packet;
35 int len;
36 void *data;
37 int port;
38 int times;
39 struct packetqq *next;
42 static struct packetqq *pqh=NULL;
43 static struct packetqq *pqt=NULL;
44 static struct timeval last_try;
46 void packetq_add(int (*sender)(int fd, int fd_ctl, void *packet, int len, void *data, int port),
47 int fd, int fd_ctl, void *packet, int len, void *data, int port)
49 if (countq < MAXQLEN) {
50 struct packetqq *new=malloc(sizeof(struct packetqq));
51 void *packetcopy=malloc(len);
52 if (new != NULL && packetcopy != NULL && len > 0) {
53 countq++;
54 new->sender=sender;
55 new->fd=fd;
56 new->fd_ctl=fd_ctl;
57 memcpy(packetcopy,packet,len);
58 new->packet=packetcopy;
59 new->len=len;
60 new->data=data;
61 new->port=port;
62 new->times=TIMES;
63 new->next=NULL;
64 if (pqh==NULL) {
65 gettimeofday(&last_try,NULL);
66 packetq_timeout=TIMEOUT;
67 pqh=pqt=new;
68 } else {
69 pqt->next=new;
70 pqt=new;
72 } else {
73 if (new != NULL) free(new);
74 if (packetcopy != NULL) free(packetcopy);
79 static struct packetqq *packetq_scantry(struct packetqq *h,struct packetqq **t,fd_set *fds)
81 if (h != NULL) {
82 int sendrv=!(FD_ISSET(h->fd,fds));
83 h->times--;
84 if ((sendrv && (sendrv=h->sender(h->fd,h->fd_ctl,h->packet,h->len,h->data,h->port)) == 0) /*send OK*/
85 || h->times<=0) { /*or max number of attempts reached*/
86 struct packetqq *next;
87 #if 0
88 /* this error code is unreachable! (sendrv==0 here) */
89 if (sendrv != 0) {
90 if (sendrv < 0)
91 printlog(LOG_WARNING,"packetqueue port %d: %s",h->port,strerror(-sendrv));
92 else
93 printlog(LOG_WARNING,"packetqueue port %d: partial send (%d bytes lost)",h->port,sendrv);
95 #endif
96 next=h->next;
97 countq--;
98 free(h->packet);
99 free(h);
100 return packetq_scantry(next,t,fds);
101 } else {
102 FD_SET(h->fd,fds);
103 h->next=packetq_scantry(h->next,t,fds);
104 if (h->next == NULL) *t=h;
105 return h;
107 } else
108 return NULL;
111 void packetq_try(void)
113 if (pqh != NULL) {
114 struct timeval this_try;
115 gettimeofday(&this_try,NULL);
116 packetq_timeout=TIMEOUT - ((this_try.tv_sec-last_try.tv_sec) * 1000 +
117 (this_try.tv_usec-last_try.tv_usec) / 1000);
118 if (packetq_timeout <= 0) {
119 fd_set fds;
120 FD_ZERO(&fds);
121 pqh=packetq_scantry(pqh,&pqt,&fds);
122 if (pqh != NULL) {
123 gettimeofday(&last_try,NULL);
124 packetq_timeout=TIMEOUT;
125 } else
126 packetq_timeout = -1;
131 static struct packetqq *packetq_scandelfd(int fd,struct packetqq *h,struct packetqq **t)
133 if (h != NULL) {
134 if (fd == h->fd) {
135 struct packetqq *next=h->next;
136 countq--;
137 free(h->packet);
138 free(h);
139 return packetq_scandelfd(fd,next,t);
140 } else {
141 h->next=packetq_scandelfd(fd,h->next,t);
142 if (h->next == NULL) *t=h;
143 return h;
145 } else
146 return NULL;
149 void packetq_delfd(int fd)
151 pqh=packetq_scandelfd(fd,pqh,&pqt);
152 if (pqh == NULL)
153 packetq_timeout = -1;
156 int packetq_count()
158 return countq;
160 #endif