Browse Source

Network API now allows for multiple network devices (although the

implementation allows for only one, and does so without compromising on
the efficiency of static allocation).

Link-layer protocols are cleanly separated from the device drivers.

Network-layer protocols are cleanly separated from individual network
devices.

Link-layer and network-layer protocols are cleanly separated from each
other.
tags/v0.9.3
Michael Brown 18 years ago
parent
commit
53f78346bf
4 changed files with 319 additions and 137 deletions
  1. 28
    0
      src/include/gpxe/ethernet.h
  2. 226
    0
      src/net/ipv4.c
  3. 65
    0
      src/net/pkbuff.c
  4. 0
    137
      src/proto/ip.c

+ 28
- 0
src/include/gpxe/ethernet.h View File

@@ -0,0 +1,28 @@
1
+#ifndef _GPXE_ETHERNET_H
2
+#define _GPXE_ETHERNET_H
3
+
4
+/** @file
5
+ *
6
+ * Ethernet protocol
7
+ *
8
+ */
9
+
10
+#include <stdint.h>
11
+#include <gpxe/netdevice.h>
12
+
13
+extern struct ll_protocol ethernet_protocol;
14
+
15
+/**
16
+ * Allocate Ethernet device
17
+ *
18
+ * @v priv_size		Size of driver private data
19
+ * @ret netdev		Network device, or NULL
20
+ */
21
+#define alloc_etherdev( priv_size ) ( {				\
22
+	struct net_device *netdev;				\
23
+	netdev = alloc_netdev ( priv_size );			\
24
+	if ( netdev )						\
25
+		netdev->ll_protocol = &ethernet_protocol;	\
26
+	netdev;	} )
27
+
28
+#endif /* _GPXE_ETHERNET_H */

+ 226
- 0
src/net/ipv4.c View File

@@ -0,0 +1,226 @@
1
+#include <string.h>
2
+#include <stdint.h>
3
+#include <byteswap.h>
4
+#include <gpxe/in.h>
5
+
6
+
7
+#include <ip.h>
8
+
9
+
10
+#include <gpxe/if_ether.h>
11
+#include <gpxe/pkbuff.h>
12
+#include <gpxe/netdevice.h>
13
+#include "../proto/uip/uip.h"
14
+
15
+/** @file
16
+ *
17
+ * IPv4 protocol
18
+ *
19
+ * The gPXE IP stack is currently implemented on top of the uIP
20
+ * protocol stack.  This file provides wrappers around uIP so that
21
+ * higher-level protocol implementations do not need to talk directly
22
+ * to uIP (which has a somewhat baroque API).
23
+ *
24
+ */
25
+
26
+/** An IPv4 routing table entry */
27
+struct ipv4_route {
28
+	/** Network address */
29
+	struct in_addr network;
30
+	/** Subnet mask */
31
+	struct in_addr netmask;
32
+	/** Gateway address */
33
+	struct in_addr gateway;
34
+	/** Gateway device */
35
+	struct in_addr gatewaydev;
36
+};
37
+
38
+enum {
39
+	STATIC_SINGLE_NETDEV_ROUTE = 0,
40
+	DEFAULT_ROUTE,
41
+	NUM_ROUTES
42
+};
43
+
44
+/** IPv4 routing table */
45
+static struct ipv4_route routing_table[NUM_ROUTES];
46
+
47
+#define routing_table_end ( routing_table + NUM_ROUTES )
48
+
49
+#if 0
50
+/**
51
+ * Set IP address
52
+ *
53
+ */
54
+void set_ipaddr ( struct in_addr address ) {
55
+	union {
56
+		struct in_addr address;
57
+		uint16_t uip_address[2];
58
+	} u;
59
+
60
+	u.address = address;
61
+	uip_sethostaddr ( u.uip_address );
62
+}
63
+
64
+/**
65
+ * Set netmask
66
+ *
67
+ */
68
+void set_netmask ( struct in_addr address ) {
69
+	union {
70
+		struct in_addr address;
71
+		uint16_t uip_address[2];
72
+	} u;
73
+
74
+	u.address = address;
75
+	uip_setnetmask ( u.uip_address );
76
+}
77
+
78
+/**
79
+ * Set default gateway
80
+ *
81
+ */
82
+void set_gateway ( struct in_addr address ) {
83
+	union {
84
+		struct in_addr address;
85
+		uint16_t uip_address[2];
86
+	} u;
87
+
88
+	u.address = address;
89
+	uip_setdraddr ( u.uip_address );
90
+}
91
+
92
+/**
93
+ * Run the TCP/IP stack
94
+ *
95
+ * Call this function in a loop in order to allow TCP/IP processing to
96
+ * take place.  This call takes the stack through a single iteration;
97
+ * it will typically be used in a loop such as
98
+ *
99
+ * @code
100
+ *
101
+ * struct tcp_connection *my_connection;
102
+ * ...
103
+ * tcp_connect ( my_connection );
104
+ * while ( ! my_connection->finished ) {
105
+ *   run_tcpip();
106
+ * }
107
+ *
108
+ * @endcode
109
+ *
110
+ * where @c my_connection->finished is set by one of the connection's
111
+ * #tcp_operations methods to indicate completion.
112
+ */
113
+void run_tcpip ( void ) {
114
+	void *data;
115
+	size_t len;
116
+	uint16_t type;
117
+	int i;
118
+	
119
+	if ( netdev_poll ( 1, &data, &len ) ) {
120
+		/* We have data */
121
+		memcpy ( uip_buf, data, len );
122
+		uip_len = len;
123
+		type = ntohs ( *( ( uint16_t * ) ( uip_buf + 12 ) ) );
124
+		if ( type == UIP_ETHTYPE_ARP ) {
125
+			uip_arp_arpin();
126
+		} else {
127
+			uip_arp_ipin();
128
+			uip_input();
129
+		}
130
+		if ( uip_len > 0 )
131
+			uip_transmit();
132
+	} else {
133
+		for ( i = 0 ; i < UIP_CONNS ; i++ ) {
134
+			uip_periodic ( i );
135
+			if ( uip_len > 0 )
136
+				uip_transmit();
137
+		}
138
+	}
139
+}
140
+#endif
141
+
142
+/**
143
+ * Process incoming IP packets
144
+ *
145
+ * @v pkb		Packet buffer
146
+ * @ret rc		Return status code
147
+ *
148
+ * This handles IP packets by handing them off to the uIP protocol
149
+ * stack.
150
+ */
151
+static int ipv4_rx ( struct pk_buff *pkb ) {
152
+
153
+	/* Transfer to uIP buffer.  Horrendously space-inefficient,
154
+	 * but will do as a proof-of-concept for now.
155
+	 */
156
+	memcpy ( uip_buf, pkb->data, pkb_len ( pkb ) );
157
+
158
+	/* Hand to uIP for processing */
159
+	uip_input ();
160
+	if ( uip_len > 0 ) {
161
+		pkb_empty ( pkb );
162
+		pkb_put ( pkb, uip_len );
163
+		memcpy ( pkb->data, uip_buf, uip_len );
164
+		if ( net_transmit ( pkb ) != 0 )
165
+			free_pkb ( pkb );
166
+	} else {
167
+		free_pkb ( pkb );
168
+	}
169
+	return 0;
170
+}
171
+
172
+/**
173
+ * Perform IP layer routing
174
+ *
175
+ * @v pkb	Packet buffer
176
+ * @ret source	Network-layer source address
177
+ * @ret dest	Network-layer destination address
178
+ * @ret rc	Return status code
179
+ */
180
+static int ipv4_route ( const struct pk_buff *pkb,
181
+			struct net_header *nethdr ) {
182
+	struct iphdr *iphdr = pkb->data;
183
+	struct in_addr *source = ( struct in_addr * ) nethdr->source_net_addr;
184
+	struct in_addr *dest = ( struct in_addr * ) nethdr->dest_net_addr;
185
+	struct ipv4_route *route;
186
+
187
+	/* Route IP packet according to routing table */
188
+	source->s_addr = INADDR_NONE;
189
+	dest->s_addr = iphdr->dest.s_addr;
190
+	for ( route = routing_table ; route < routing_table_end ; route++ ) {
191
+		if ( ( dest->s_addr & route->netmask.s_addr )
192
+		     == route->network.s_addr ) {
193
+			source->s_addr = route->gatewaydev.s_addr;
194
+			if ( route->gateway.s_addr )
195
+				dest->s_addr = route->gateway.s_addr;
196
+			break;
197
+		}
198
+	}
199
+
200
+	/* Set broadcast and multicast flags as applicable */
201
+	nethdr->dest_flags = 0;
202
+	if ( dest->s_addr == htonl ( INADDR_BROADCAST ) ) {
203
+		nethdr->dest_flags = NETADDR_FL_BROADCAST;
204
+	} else if ( IN_MULTICAST ( dest->s_addr ) ) {
205
+		nethdr->dest_flags = NETADDR_FL_MULTICAST;
206
+	}
207
+
208
+	return 0;
209
+}
210
+
211
+/** IPv4 protocol */
212
+struct net_protocol ipv4_protocol = {
213
+	.net_proto = ETH_P_IP,
214
+	.net_addr_len = sizeof ( struct in_addr ),
215
+	.rx = ipv4_rx,
216
+	.route = ipv4_route,
217
+};
218
+
219
+NET_PROTOCOL ( ipv4_protocol );
220
+
221
+/** IPv4 address for the static single net device */
222
+struct net_address static_single_ipv4_address = {
223
+	.net_protocol = &ipv4_protocol,
224
+};
225
+
226
+STATIC_SINGLE_NETDEV_ADDRESS ( static_single_ipv4_address );

+ 65
- 0
src/net/pkbuff.c View File

@@ -0,0 +1,65 @@
1
+/*
2
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
3
+ *
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License as
6
+ * published by the Free Software Foundation; either version 2 of the
7
+ * License, or any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful, but
10
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
+ */
18
+
19
+#include <stdint.h>
20
+#include <gpxe/malloc.h>
21
+#include <gpxe/pkbuff.h>
22
+
23
+/** @file
24
+ *
25
+ * Packet buffers
26
+ *
27
+ */
28
+
29
+/**
30
+ * Allocate packet buffer
31
+ *
32
+ * @v len	Required length of buffer
33
+ * @ret pkb	Packet buffer, or NULL if none available
34
+ *
35
+ * The packet buffer will be aligned as per gmalloc().
36
+ */
37
+struct pk_buff * alloc_pkb ( size_t len ) {
38
+	struct pk_buff *pkb = NULL;
39
+	void *data;
40
+
41
+	/* Align buffer length */
42
+	len = ( len + __alignof__ ( *pkb ) - 1 ) & ~ __alignof__ ( *pkb );
43
+	
44
+	/* Allocate memory for buffer plus descriptor */
45
+	data = gmalloc ( len + sizeof ( *pkb ) );
46
+	if ( ! data )
47
+		return NULL;
48
+
49
+	pkb = ( struct pk_buff * ) ( data + len );
50
+	pkb->head = pkb->data = pkb->tail = data;
51
+	pkb->end = pkb;
52
+	return pkb;
53
+}
54
+
55
+/**
56
+ * Free packet buffer
57
+ *
58
+ * @v pkb	Packet buffer
59
+ */
60
+void free_pkb ( struct pk_buff *pkb ) {
61
+	if ( pkb ) {
62
+		gfree ( pkb->head,
63
+			( pkb->end - pkb->head ) + sizeof ( *pkb ) );
64
+	}
65
+}

+ 0
- 137
src/proto/ip.c View File

@@ -1,137 +0,0 @@
1
-#include <string.h>
2
-#include <stdint.h>
3
-#include <byteswap.h>
4
-#include <gpxe/in.h>
5
-#include <gpxe/ip.h>
6
-#include "uip/uip.h"
7
-#include "uip/uip_arp.h"
8
-
9
-/** @file
10
- *
11
- * IP protocol
12
- *
13
- * The gPXE IP stack is currently implemented on top of the uIP
14
- * protocol stack.  This file provides wrappers around uIP so that
15
- * higher-level protocol implementations do not need to talk directly
16
- * to uIP (which has a somewhat baroque API).
17
- *
18
- */
19
-
20
-/**
21
- * Set IP address
22
- *
23
- */
24
-void set_ipaddr ( struct in_addr address ) {
25
-	union {
26
-		struct in_addr address;
27
-		uint16_t uip_address[2];
28
-	} u;
29
-
30
-	u.address = address;
31
-	uip_sethostaddr ( u.uip_address );
32
-}
33
-
34
-/**
35
- * Set netmask
36
- *
37
- */
38
-void set_netmask ( struct in_addr address ) {
39
-	union {
40
-		struct in_addr address;
41
-		uint16_t uip_address[2];
42
-	} u;
43
-
44
-	u.address = address;
45
-	uip_setnetmask ( u.uip_address );
46
-}
47
-
48
-/**
49
- * Set default gateway
50
- *
51
- */
52
-void set_gateway ( struct in_addr address ) {
53
-	union {
54
-		struct in_addr address;
55
-		uint16_t uip_address[2];
56
-	} u;
57
-
58
-	u.address = address;
59
-	uip_setdraddr ( u.uip_address );
60
-}
61
-
62
-/**
63
- * Initialise TCP/IP stack
64
- *
65
- */
66
-void init_tcpip ( void ) {
67
-	uip_init();
68
-	uip_arp_init();
69
-}
70
-
71
-#define UIP_HLEN ( 40 + UIP_LLH_LEN )
72
-
73
-/**
74
- * Transmit TCP data
75
- *
76
- * This is a wrapper around netdev_transmit().  It gathers up the
77
- * packet produced by uIP, and then passes it to netdev_transmit() as
78
- * a single buffer.
79
- */
80
-static void uip_transmit ( void ) {
81
-	uip_arp_out();
82
-	if ( uip_len > UIP_HLEN ) {
83
-		memcpy ( uip_buf + UIP_HLEN, ( void * ) uip_appdata,
84
-			 uip_len - UIP_HLEN );
85
-	}
86
-	netdev_transmit ( uip_buf, uip_len );
87
-	uip_len = 0;
88
-}
89
-
90
-/**
91
- * Run the TCP/IP stack
92
- *
93
- * Call this function in a loop in order to allow TCP/IP processing to
94
- * take place.  This call takes the stack through a single iteration;
95
- * it will typically be used in a loop such as
96
- *
97
- * @code
98
- *
99
- * struct tcp_connection *my_connection;
100
- * ...
101
- * tcp_connect ( my_connection );
102
- * while ( ! my_connection->finished ) {
103
- *   run_tcpip();
104
- * }
105
- *
106
- * @endcode
107
- *
108
- * where @c my_connection->finished is set by one of the connection's
109
- * #tcp_operations methods to indicate completion.
110
- */
111
-void run_tcpip ( void ) {
112
-	void *data;
113
-	size_t len;
114
-	uint16_t type;
115
-	int i;
116
-	
117
-	if ( netdev_poll ( 1, &data, &len ) ) {
118
-		/* We have data */
119
-		memcpy ( uip_buf, data, len );
120
-		uip_len = len;
121
-		type = ntohs ( *( ( uint16_t * ) ( uip_buf + 12 ) ) );
122
-		if ( type == UIP_ETHTYPE_ARP ) {
123
-			uip_arp_arpin();
124
-		} else {
125
-			uip_arp_ipin();
126
-			uip_input();
127
-		}
128
-		if ( uip_len > 0 )
129
-			uip_transmit();
130
-	} else {
131
-		for ( i = 0 ; i < UIP_CONNS ; i++ ) {
132
-			uip_periodic ( i );
133
-			if ( uip_len > 0 )
134
-				uip_transmit();
135
-		}
136
-	}
137
-}

Loading…
Cancel
Save