Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


updates
[palacios.git] / geekos / src / lwip / netif / loopif.c
1 /**
2  * @file
3  * Loop Interface
4  *
5  */
6
7 /*
8  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
9  * All rights reserved. 
10  * 
11  * Redistribution and use in source and binary forms, with or without modification, 
12  * are permitted provided that the following conditions are met:
13  *
14  * 1. Redistributions of source code must retain the above copyright notice,
15  *    this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright notice,
17  *    this list of conditions and the following disclaimer in the documentation
18  *    and/or other materials provided with the distribution.
19  * 3. The name of the author may not be used to endorse or promote products
20  *    derived from this software without specific prior written permission. 
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
23  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
24  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
25  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
26  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
27  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
30  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
31  * OF SUCH DAMAGE.
32  *
33  * This file is part of the lwIP TCP/IP stack.
34  * 
35  * Author: Adam Dunkels <adam@sics.se>
36  *
37  */
38 #include "lwip/opt.h"
39
40 #if LWIP_HAVE_LOOPIF
41
42 #include "netif/loopif.h"
43 #include "lwip/pbuf.h"
44 #include "lwip/snmp.h"
45
46 #include <string.h>
47
48 #if !LWIP_LOOPIF_MULTITHREADING
49
50 #include "lwip/sys.h"
51 #include "lwip/mem.h"
52
53 /* helper struct for the linked list of pbufs */
54 struct loopif_private {
55   struct pbuf *first;
56   struct pbuf *last;
57 };
58
59 /**
60  * Call loopif_poll() in the main loop of your application. This is to prevent
61  * reentering non-reentrant functions like tcp_input(). Packets passed to
62  * loopif_output() are put on a list that is passed to netif->input() by
63  * loopif_poll().
64  *
65  * @param netif the lwip network interface structure for this loopif
66  */
67 void
68 loopif_poll(struct netif *netif)
69 {
70   SYS_ARCH_DECL_PROTECT(lev);
71   struct pbuf *in, *in_end;
72   struct loopif_private *priv = (struct loopif_private*)netif->state;
73
74   LWIP_ERROR("priv != NULL", (priv != NULL), return;);
75
76   do {
77     /* Get a packet from the list. With SYS_LIGHTWEIGHT_PROT=1, this is protected */
78     SYS_ARCH_PROTECT(lev);
79     in = priv->first;
80     if(in) {
81       in_end = in;
82       while(in_end->len != in_end->tot_len) {
83         LWIP_ASSERT("bogus pbuf: len != tot_len but next == NULL!", in_end->next != NULL);
84         in_end = in_end->next;
85       }
86       /* 'in_end' now points to the last pbuf from 'in' */
87       if(in_end == priv->last) {
88         /* this was the last pbuf in the list */
89         priv->first = priv->last = NULL;
90       } else {
91         /* pop the pbuf off the list */
92         priv->first = in_end->next;
93         LWIP_ASSERT("should not be null since first != last!", priv->first != NULL);
94       }
95     }
96     SYS_ARCH_UNPROTECT(lev);
97   
98     if(in != NULL) {
99       if(in_end->next != NULL) {
100         /* De-queue the pbuf from its successors on the 'priv' list. */
101         in_end->next = NULL;
102       }
103       if(netif->input(in, netif) != ERR_OK) {
104         pbuf_free(in);
105       }
106       /* Don't reference the packet any more! */
107       in = NULL;
108       in_end = NULL;
109     }
110   /* go on while there is a packet on the list */
111   } while(priv->first != NULL);
112 }
113 #endif /* LWIP_LOOPIF_MULTITHREADING */
114
115 /**
116  * Send an IP packet over the loopback interface.
117  * The pbuf is simply copied and handed back to netif->input.
118  * In multithreaded mode, this is done directly since netif->input must put
119  * the packet on a queue.
120  * In callback mode, the packet is put on an internal queue and is fed to
121  * netif->input by loopif_poll().
122  *
123  * @param netif the lwip network interface structure for this loopif
124  * @param p the (IP) packet to 'send'
125  * @param ipaddr the ip address to send the packet to (not used for loopif)
126  * @return ERR_OK if the packet has been sent
127  *         ERR_MEM if the pbuf used to copy the packet couldn't be allocated
128  */
129 static err_t
130 loopif_output(struct netif *netif, struct pbuf *p,
131        struct ip_addr *ipaddr)
132 {
133 #if !LWIP_LOOPIF_MULTITHREADING
134   SYS_ARCH_DECL_PROTECT(lev);
135   struct loopif_private *priv;
136   struct pbuf *last;
137 #endif /* LWIP_LOOPIF_MULTITHREADING */
138   struct pbuf *r;
139   err_t err;
140
141   LWIP_UNUSED_ARG(ipaddr);
142
143   /* Allocate a new pbuf */
144   r = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
145   if (r == NULL) {
146     return ERR_MEM;
147   }
148
149   /* Copy the whole pbuf queue p into the single pbuf r */
150   if ((err = pbuf_copy(r, p)) != ERR_OK) {
151     pbuf_free(r);
152     r = NULL;
153     return err;
154   }
155
156 #if LWIP_LOOPIF_MULTITHREADING
157   /* Multithreading environment, netif->input() is supposed to put the packet
158      into a mailbox, so we can safely call it here without risking to re-enter
159      functions that are not reentrant (TCP!!!) */
160   if(netif->input(r, netif) != ERR_OK) {
161     pbuf_free(r);
162     r = NULL;
163   }
164 #else /* LWIP_LOOPIF_MULTITHREADING */
165   /* Raw API without threads: put the packet on a linked list which gets emptied
166      through calling loopif_poll(). */
167   priv = (struct loopif_private*)netif->state;
168
169   /* let last point to the last pbuf in chain r */
170   for (last = r; last->next != NULL; last = last->next);
171   SYS_ARCH_PROTECT(lev);
172   if(priv->first != NULL) {
173     LWIP_ASSERT("if first != NULL, last must also be != NULL", priv->last != NULL);
174     priv->last->next = r;
175     priv->last = last;
176   } else {
177     priv->first = r;
178     priv->last = last;
179   }
180   SYS_ARCH_UNPROTECT(lev);
181 #endif /* LWIP_LOOPIF_MULTITHREADING */
182
183   return ERR_OK;    
184 }
185
186 /**
187  * Initialize a lwip network interface structure for a loopback interface
188  *
189  * @param netif the lwip network interface structure for this loopif
190  * @return ERR_OK if the loopif is initialized
191  *         ERR_MEM if private data couldn't be allocated
192  */
193 err_t
194 loopif_init(struct netif *netif)
195 {
196 #if !LWIP_LOOPIF_MULTITHREADING
197   struct loopif_private *priv;
198
199   priv = (struct loopif_private*)mem_malloc(sizeof(struct loopif_private));
200   if(priv == NULL) 
201     return ERR_MEM;
202   priv->first = priv->last = NULL;
203   netif->state = priv;
204 #endif /* LWIP_LOOPIF_MULTITHREADING */
205
206   /* initialize the snmp variables and counters inside the struct netif
207    * ifSpeed: no assumption can be made!
208    */
209   NETIF_INIT_SNMP(netif, snmp_ifType_softwareLoopback, 0);
210
211   netif->name[0] = 'l';
212   netif->name[1] = 'o';
213   netif->output = loopif_output;
214   return ERR_OK;
215 }
216
217 #endif /* LWIP_HAVE_LOOPIF */