1 |
786 |
skrzyp |
|
2 |
|
|
|
3 |
|
|
|
4 |
|
|
|
5 |
|
|
|
6 |
|
|
|
7 |
|
|
|
8 |
|
|
|
9 |
|
|
|
10 |
|
|
|
11 |
|
|
|
12 |
|
|
|
13 |
|
|
|
14 |
|
|
|
15 |
|
|
|
16 |
|
|
|
17 |
|
|
|
18 |
|
|
|
19 |
|
|
|
20 |
|
|
|
21 |
|
|
|
22 |
|
|
|
23 |
|
|
|
24 |
|
|
|
25 |
|
|
|
26 |
|
|
|
27 |
|
|
|
28 |
|
|
|
29 |
|
|
|
30 |
|
|
|
31 |
|
|
FreeBSD TCP/IP Stack port for eCos
|
32 |
|
|
|
33 |
|
|
TCP/IP Networking for eCos
|
34 |
|
|
now provides a complete
|
35 |
|
|
TCP/IP networking stack,
|
36 |
|
|
based on a snapshot of the FreeBSD code, released by the
|
37 |
|
|
KAME project.
|
38 |
|
|
The networking support is
|
39 |
|
|
fully featured and well tested within the eCos environment.
|
40 |
|
|
|
41 |
|
|
|
42 |
|
|
|
43 |
|
|
|
44 |
|
|
Networking Stack Features
|
45 |
|
|
Since this networking package is based on BSD code, it is
|
46 |
|
|
very complete and robust. The eCos implementation includes support
|
47 |
|
|
for the following protocols:
|
48 |
|
|
|
49 |
|
|
IPv4
|
50 |
|
|
UDP
|
51 |
|
|
TCP
|
52 |
|
|
ICMP
|
53 |
|
|
raw packet interface
|
54 |
|
|
Multi-cast addressing
|
55 |
|
|
IPv6 (including UDP, ICP, ICMP)
|
56 |
|
|
|
57 |
|
|
These additional features are also present in the package,
|
58 |
|
|
but are not supported:
|
59 |
|
|
|
60 |
|
|
Berkeley Packet Filter
|
61 |
|
|
Uni-cast support
|
62 |
|
|
Multi-cast routing
|
63 |
|
|
|
64 |
|
|
|
65 |
|
|
|
66 |
|
|
Freebsd TCP/IP stack port
|
67 |
|
|
This document describes how to get started with the Freebsd
|
68 |
|
|
TCP/IP network stack.
|
69 |
|
|
|
70 |
|
|
Targets
|
71 |
|
|
A number of ethernet devices may be supported. The default configuration
|
72 |
|
|
supports two instances of the interface by default,
|
73 |
|
|
and you will need to write your own driver instantiation code,
|
74 |
|
|
and supplemental startup and initialization code,
|
75 |
|
|
if you should add additional ones.
|
76 |
|
|
The target for your board will normally be supplied with an
|
77 |
|
|
ethernet driver, in which case including the network stack and
|
78 |
|
|
generic ethernet driver package to your build will automatically
|
79 |
|
|
enable usage of the ethernet device driver.
|
80 |
|
|
If your target is not supplied with an ethernet
|
81 |
|
|
driver, you will need to use loopback (see
|
82 |
|
|
).
|
83 |
|
|
|
84 |
|
|
|
85 |
|
|
Building the Network Stack
|
86 |
|
|
Using the Build->Packages dialog,
|
87 |
|
|
add the packages “Networking”,
|
88 |
|
|
“Freebsd TCP/IP Stack”
|
89 |
|
|
and “Common Ethernet Support”
|
90 |
|
|
to your configuration. Their package names
|
91 |
|
|
are CYGPKG_NET, CYGPKG_NET_FREEBSD_STACK and CYGPKG_NET_ETH_DRIVERS
|
92 |
|
|
respectively.
|
93 |
|
|
A short-cut way to do this is by
|
94 |
|
|
using the “net” template
|
95 |
|
|
if it is available for your platform.
|
96 |
|
|
The platform-specific ethernet device driver for your platform
|
97 |
|
|
will be added as part of the target selection (in the
|
98 |
|
|
Build->Templates “Hardware” item),
|
99 |
|
|
along with the
|
100 |
|
|
PCI I/O subsystem (if relevent) and the appropriate serial device driver.
|
101 |
|
|
|
102 |
|
|
For example, the PowerPC MBX target selection adds the package
|
103 |
|
|
PKG_NET_QUICC_ETH_DRIVERS,
|
104 |
|
|
and the Cirrus Logic EDB7xxx target selection adds the package
|
105 |
|
|
CYGPKG_NET_EDB7XXX_ETH_DRIVERS.
|
106 |
|
|
After this, eCos and its tests can be built exactly as usual.
|
107 |
|
|
|
108 |
|
|
By default, most of the network tests are not built. This
|
109 |
|
|
is because some of them require manual intervention, i.e. they are
|
110 |
|
|
to be run “by hand”, and are not suitable for
|
111 |
|
|
automated testing. To build the full set of network tests, set
|
112 |
|
|
the configuration option CYGPKG_NET_BUILD_TESTS “Build
|
113 |
|
|
networking tests (demo programs)” within “Networking
|
114 |
|
|
support build options”.
|
115 |
|
|
|
116 |
|
|
|
117 |
|
|
|
118 |
|
|
|
119 |
|
|
APIs
|
120 |
|
|
|
121 |
|
|
Standard networking
|
122 |
|
|
The APIs for the standard networking calls such as
|
123 |
|
|
socket(), recv() and so on, are
|
124 |
|
|
in header files relative to the top-level
|
125 |
|
|
include directory, within the standard subdirectories as conventionally
|
126 |
|
|
found in /usr/include. For example:
|
127 |
|
|
|
128 |
|
|
install/include/arpa/tftp.h
|
129 |
|
|
install/include/netinet/tcpip.h
|
130 |
|
|
install/include/sys/socket.h
|
131 |
|
|
install/include/sys/socketvar.h
|
132 |
|
|
install/include/sys/sockio.h
|
133 |
|
|
|
134 |
|
|
|
135 |
|
|
|
136 |
|
|
network.h at the top level
|
137 |
|
|
defines various extensions, for example the API
|
138 |
|
|
init_all_network_interfaces(void)
|
139 |
|
|
described
|
140 |
|
|
above. We advise including network.h whether
|
141 |
|
|
you use these features or not.
|
142 |
|
|
In general, using the networking code may require definition
|
143 |
|
|
of two symbols: _KERNEL and __ECOS. _KERNEL
|
144 |
|
|
is not normally required; __ECOS is normally required.
|
145 |
|
|
So add this to your compile lines for files which use the network
|
146 |
|
|
stack:
|
147 |
|
|
-D__ECOS
|
148 |
|
|
To expand a little, it’s like this because this is
|
149 |
|
|
a port of a standard distribution external to eCos. One goal
|
150 |
|
|
is to perturb the sources as little as possible, so that upgrading
|
151 |
|
|
and maintenance from the external distribution is simplified. The __ECOS
|
152 |
|
|
symbol marks out the eCos additions in making the port.
|
153 |
|
|
The _KERNEL symbol is traditional UNIX practice: it distinguishes
|
154 |
|
|
a compilation which is to be linked into the kernel from one which
|
155 |
|
|
is part of an application. eCos applications are fully linked,
|
156 |
|
|
so this distinction does not apply. _KERNEL can however
|
157 |
|
|
be used to control the visibility of the internals of the stack,
|
158 |
|
|
so depending on what features your application uses, it may or may
|
159 |
|
|
not be necessary.
|
160 |
|
|
The include file network.h undefines _KERNEL
|
161 |
|
|
unconditionally, to provide an application-like compilation environment.
|
162 |
|
|
If you were writing code which, for example,
|
163 |
|
|
enumerates the stack’s internal
|
164 |
|
|
structures, that is a kernel-like compilation environment, so you
|
165 |
|
|
would need to define _KERNEL (in addition to __ECOS)
|
166 |
|
|
and avoid including network.h.
|
167 |
|
|
|
168 |
|
|
|
169 |
|
|
Enhanced Select()
|
170 |
|
|
The network stack supports an extension to the standard select
|
171 |
|
|
semantics which allows all threads that are waiting to be restarted
|
172 |
|
|
even if the select conditions are not satisfied.
|
173 |
|
|
The standard select() API:
|
174 |
|
|
int
|
175 |
|
|
select(int nfd,
|
176 |
|
|
fd_set *in, fd_set *out, fd_set *ex,
|
177 |
|
|
struct timeval *tv);
|
178 |
|
|
does not support the restart.
|
179 |
|
|
The additional API:
|
180 |
|
|
int
|
181 |
|
|
cyg_select_with_abort(int nfd,
|
182 |
|
|
fd_set *in, fd_set *out, fd_set *ex,
|
183 |
|
|
struct timeval *tv)
|
184 |
|
|
|
185 |
|
|
behaves exactly as select() with the additional feature that
|
186 |
|
|
a call to
|
187 |
|
|
|
188 |
|
|
void cyg_select_abort(void)
|
189 |
|
|
|
190 |
|
|
will cause all threads waiting in any
|
191 |
|
|
cyg_select_with_abort() call
|
192 |
|
|
to cease waiting and continue execution.
|
193 |
|
|
|
194 |
|
|
|
195 |
|
|
|
196 |
|
|
Disabling IPv6 Support at Runtime
|
197 |
|
|
|
198 |
|
|
The FreeBSD stack starts up with IPv4 support in an essentially
|
199 |
|
|
"disabled" state. It requires the application to take positive actions
|
200 |
|
|
to assign IPv4 address and routes before the interfaces will respond
|
201 |
|
|
to packets from the outside world.
|
202 |
|
|
|
203 |
|
|
|
204 |
|
|
This is not true of IPv6 support. If IPv6 support was enabled in the
|
205 |
|
|
eCos build, the stack will start up with link-local addresses
|
206 |
|
|
assigned and interfaces listening to certain multicast addresses. The
|
207 |
|
|
stack will not only respond to IPv6 packets, it will spontaneously
|
208 |
|
|
send IPv6 packets without actions from application code.
|
209 |
|
|
|
210 |
|
|
|
211 |
|
|
If an eCos application wishes to disable IPv6 support at runtime, the
|
212 |
|
|
decision has to be made very early in the boot process and actions
|
213 |
|
|
taken to prevent the invocation of IPv6 startup code in the network
|
214 |
|
|
stack. This involves two rather obscure "tricks":
|
215 |
|
|
|
216 |
|
|
|
217 |
|
|
Using a dummy device driver's "init" hook as a place to execute some
|
218 |
|
|
code early in the startup process
|
219 |
|
|
|
220 |
|
|
Monkey-patching the network stack's table of
|
221 |
|
|
initializers by looping through it and checking the function pointers
|
222 |
|
|
against certain globally visible symbols and replacing the two
|
223 |
|
|
IPv6-specific function pointers with pointers to a "noop" function.
|
224 |
|
|
|
225 |
|
|
|
226 |
|
|
|
227 |
|
|
|
228 |
|
|
The code listing below shows an example of disabling IPv6 support at
|
229 |
|
|
runtime if the global variable we_want_to_disable_ipv6 is non-zero.
|
230 |
|
|
The assumption is that some code in the HAL initialization or
|
231 |
|
|
somewhere else has made the decision whether or not to disable IPv6
|
232 |
|
|
support and set that variable accordingly.
|
233 |
|
|
|
234 |
|
|
|
235 |
|
|
// Sample code showing a method of disabling IPv6 support at runtime
|
236 |
|
|
|
237 |
|
|
// Do-nothing function we can patch into the network stack's init table
|
238 |
|
|
// when we want to disable one of the entries
|
239 |
|
|
static void
|
240 |
|
|
init_noop(void *dummy)
|
241 |
|
|
{
|
242 |
|
|
}
|
243 |
|
|
|
244 |
|
|
// Function that loops through the network stack's init table and
|
245 |
|
|
// disables the two IPv6 entries
|
246 |
|
|
static void
|
247 |
|
|
disable_ipv6(void)
|
248 |
|
|
{
|
249 |
|
|
extern struct init_tab_entry __NET_INIT_TAB__[],
|
250 |
|
|
__NET_INIT_TAB_END__;
|
251 |
|
|
struct init_tab_entry *init_entry;
|
252 |
|
|
extern void cyg_net_add_domain(void *);
|
253 |
|
|
extern void ip6_init2(void *);
|
254 |
|
|
extern char inet6domain[];
|
255 |
|
|
|
256 |
|
|
for (init_entry = __NET_INIT_TAB__; init_entry != &__NET_INIT_TAB_END__;
|
257 |
|
|
init_entry++)
|
258 |
|
|
if ((init_entry->fun == ip6_init2)
|
259 |
|
|
|| (init_entry->fun == cyg_net_add_domain
|
260 |
|
|
&& init_entry->data == (void *)inet6domain))
|
261 |
|
|
init_entry->fun = init_noop;
|
262 |
|
|
}
|
263 |
|
|
|
264 |
|
|
// Function called early in the inintialization process via a dummy
|
265 |
|
|
// device table entry
|
266 |
|
|
static bool
|
267 |
|
|
early_init(struct cyg_devtab_entry *tab)
|
268 |
|
|
{
|
269 |
|
|
if (we_want_to_disable_ipv6)
|
270 |
|
|
disable_ipv6();
|
271 |
|
|
return 0;
|
272 |
|
|
}
|
273 |
|
|
|
274 |
|
|
// Dummy device driver table entry that will call the above early_init()
|
275 |
|
|
// function during the startup process
|
276 |
|
|
DEVTAB_ENTRY(device_master_early_init,
|
277 |
|
|
"neveruse",
|
278 |
|
|
NULL,
|
279 |
|
|
NULL,
|
280 |
|
|
early_init,
|
281 |
|
|
NULL,
|
282 |
|
|
NULL
|
283 |
|
|
);
|
284 |
|
|
|
285 |
|
|
|
286 |
|
|
|
287 |
|
|
|