[RFC v2 11/16] net: add initial picotcp support

Antony Pavlov antonynpavlov at gmail.com
Sun Jul 19 13:07:18 PDT 2015


This commit adds initial picotcp support:

 * build stuff (Kbuild fixes and fake stdint.h);
 * "pico_adapter" code for connecting barebox ethernet interfaces
   to picotcp;
 * picotcp start initialization and necessary poller.

Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
Signed-off-by: Daniele Lacamera <daniele.lacamera at tass.be>
---
 Makefile               |  1 +
 commands/Kconfig       |  4 +++
 include/net.h          | 37 ++++++++++++++++++++++-
 include/pico_defines.h |  0
 include/stdint.h       |  1 +
 net/Kconfig            | 16 ++++++++++
 net/Makefile           |  3 ++
 net/eth.c              | 71 +++++++++++++++++++++++++++++++++++++++++++
 net/net.c              | 81 +++++++++++++++++++++++++++++++++++++++++++++++++-
 net/picotcp.c          | 20 +++++++++++++
 10 files changed, 232 insertions(+), 2 deletions(-)

diff --git a/Makefile b/Makefile
index 5a7fd5f..972b5db 100644
--- a/Makefile
+++ b/Makefile
@@ -292,6 +292,7 @@ export MODVERDIR := $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/).tmp_ve
 # Use LINUXINCLUDE when you must reference the include/ directory.
 # Needed to be compatible with the O= option
 LINUXINCLUDE    := -Iinclude -I$(srctree)/dts/include \
+                   -I$(srctree)/net/picotcp/include -I$(srctree)/net/picotcp/modules \
                    $(if $(KBUILD_SRC), -I$(srctree)/include) \
 		   -I$(srctree)/arch/$(ARCH)/include \
 		   -I$(objtree)/arch/$(ARCH)/include \
diff --git a/commands/Kconfig b/commands/Kconfig
index 5571902..77193cb 100644
--- a/commands/Kconfig
+++ b/commands/Kconfig
@@ -1184,6 +1184,7 @@ menu "Network"
 config CMD_DHCP
 	bool
 	select NET_DHCP
+	depends on NET_LEGACY
 	prompt "dhcp"
 	help
 	  DHCP client to obtain IP or boot params
@@ -1210,6 +1211,7 @@ config CMD_HOST
 config NET_CMD_IFUP
 	bool
 	prompt "ifup"
+	depends on NET_LEGACY
 	help
 	  Bring up network interfaces based on config files.
 
@@ -1237,6 +1239,7 @@ config CMD_MIITOOL
 
 config CMD_PING
 	tristate
+	depends on NET_LEGACY
 	prompt "ping"
 	help
 	  Send ICMP echo requests.
@@ -1245,6 +1248,7 @@ config CMD_PING
 
 config CMD_TFTP
 	depends on FS_TFTP
+	depends on NET_LEGACY
 	tristate
 	prompt "tftp"
 	help
diff --git a/include/net.h b/include/net.h
index ed63d3c..5f2d470 100644
--- a/include/net.h
+++ b/include/net.h
@@ -24,6 +24,10 @@
 #include <linux/string.h>	/* memcpy */
 #include <asm/byteorder.h>	/* for nton* / ntoh* stuff */
 
+#include <pico_stack.h>
+#include <pico_socket.h>
+#include <pico_ipv4.h>
+
 /* How often do we retry to send packages */
 #define PKT_NUM_RETRIES 4
 
@@ -44,6 +48,7 @@ struct eth_device {
 	int  (*get_ethaddr) (struct eth_device*, u8 adr[6]);
 	int  (*set_ethaddr) (struct eth_device*, const unsigned char *adr);
 
+	struct pico_device *picodev;
 	struct eth_device *next;
 	void *priv;
 
@@ -433,6 +438,8 @@ struct net_connection {
 	void *handler;
 	int proto;
 	void *priv;
+	struct pico_socket *sock;
+	uint16_t remote_port;
 };
 
 static inline char *net_alloc_packet(void)
@@ -450,10 +457,28 @@ void net_unregister(struct net_connection *con);
 
 static inline int net_udp_bind(struct net_connection *con, uint16_t sport)
 {
+	if (IS_ENABLED(CONFIG_NET_PICOTCP)) {
+		union pico_address local_address;
+		uint16_t localport;
+
+		/* FIXME: use local_address == PICO_IPV4_INADDR_ANY */
+		memset(&local_address, 0, sizeof(union pico_address));
+
+		localport = ntohs(sport);
+
+		/* FIXME: check pico_socket_bind() return value */
+		pico_socket_bind(con->sock, &local_address, &localport);
+
+		return 0;
+	}
+
 	con->udp->uh_sport = ntohs(sport);
 	return 0;
 }
 
+#define UDP_PAYLOAD_SIZE (PKTSIZE - sizeof(struct ethernet) - sizeof(struct iphdr) - \
+		sizeof(struct udphdr))
+
 static inline void *net_udp_get_payload(struct net_connection *con)
 {
 	return con->packet + sizeof(struct ethernet) + sizeof(struct iphdr) +
@@ -475,6 +500,10 @@ static inline uint16_t getudppeerport(struct net_connection *con)
 {
 	struct udphdr *udp = net_eth_to_udphdr(con->rpacket);
 
+	if (IS_ENABLED(CONFIG_NET_PICOTCP)) {
+		return con->remote_port;
+	}
+
 	return udp->uh_sport;
 }
 
@@ -482,7 +511,13 @@ static inline uint16_t getudppeerport(struct net_connection *con)
 
 static inline void setudppeerport(struct net_connection *con, uint16_t dport)
 {
-	con->udp->uh_dport = dport;
+	if (IS_ENABLED(CONFIG_NET_LEGACY)) {
+		con->udp->uh_dport = dport;
+	} else if (IS_ENABLED(CONFIG_NET_PICOTCP)) {
+		/* FIXME */
+//		pico_socket_connect(npriv->con->sock, &remote_address, dport);
+		con->sock->remote_port = dport;
+	}
 }
 
 #endif /* __NET_H__ */
diff --git a/include/pico_defines.h b/include/pico_defines.h
new file mode 100644
index 0000000..e69de29
diff --git a/include/stdint.h b/include/stdint.h
new file mode 100644
index 0000000..029276e
--- /dev/null
+++ b/include/stdint.h
@@ -0,0 +1 @@
+/* fake stdint.h for picotcp */
diff --git a/net/Kconfig b/net/Kconfig
index a890492..f8f660c 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -3,6 +3,18 @@ menuconfig NET
 
 if NET
 
+choice
+	prompt "network stack implementation"
+
+config NET_LEGACY
+	bool "legacy U-Boot network stack"
+
+config NET_PICOTCP
+	bool "picotcp network stack"
+	select POLLER
+
+endchoice
+
 config NET_NFS
 	bool
 	prompt "nfs support"
@@ -20,10 +32,14 @@ config NET_RESOLV
 
 config NET_IFUP
 	default y
+	depends on NET_LEGACY
 	bool
 
 config NET_DHCP
 	bool
+	depends on NET_LEGACY
 	prompt "dhcp support"
 
+source "net/picotcp/Kconfig"
+
 endif
diff --git a/net/Makefile b/net/Makefile
index 8d564e7..7a4597d 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -7,3 +7,6 @@ obj-$(CONFIG_CMD_PING)	+= ping.o
 obj-$(CONFIG_NET_RESOLV)+= dns.o
 obj-$(CONFIG_NET_NETCONSOLE) += netconsole.o
 obj-$(CONFIG_NET_IFUP)	+= ifup.o
+
+obj-$(CONFIG_NET_PICOTCP) += picotcp/
+obj-$(CONFIG_NET_PICOTCP) += picotcp.o
diff --git a/net/eth.c b/net/eth.c
index a090961..34358f6 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -328,6 +328,73 @@ static int eth_register_of_fixup(void)
 late_initcall(eth_register_of_fixup);
 #endif
 
+#ifdef CONFIG_NET_PICO_SUPPORT_ETH
+
+#include <pico_stack.h>
+#include <pico_ipv4.h>
+
+struct pico_device_barebox_eth {
+	struct pico_device dev;
+	struct eth_device *edev;
+};
+
+static int pico_adapter_send(struct pico_device *dev, void *buf, int len)
+{
+	struct pico_device_barebox_eth *t = (struct pico_device_barebox_eth *)dev;
+	struct eth_device *edev = t->edev;
+
+	pr_debug("pico_adapter_send barebox eth (len=%d)\n", len);
+	edev->send(edev, buf, len);
+
+	return len;
+}
+
+static int pico_adapter_poll(struct pico_device *dev, int loop_score)
+{
+	struct pico_device_barebox_eth *t = (struct pico_device_barebox_eth *)dev;
+	struct eth_device *edev = t->edev;
+
+	/* pico_stack_recv(dev, buf, len) will be called from net_receive */
+
+	edev->recv(edev);
+
+	return loop_score;
+}
+
+static void pico_adapter_destroy(struct pico_device *dev)
+{
+	printf("pico_adapter_destroy barebox eth\n");
+}
+
+static void pico_adapter_init(struct eth_device *edev)
+{
+	/* FIXME: get macaddr for edev */
+	static unsigned char macaddr0[6] = { 0, 0, 0, 0xa, 0xb, 0xc };
+
+	struct pico_device_barebox_eth *pif = PICO_ZALLOC(sizeof(struct pico_device_barebox_eth));
+
+	struct pico_device *picodev;
+
+	char *name = strdup(edev->dev.name);
+
+	picodev = &pif->dev;
+	if (0 != pico_device_init(picodev, name, macaddr0)) {
+		pr_info("pico_adapter_init failed.\n");
+		pico_adapter_destroy(picodev);
+		return;
+	}
+
+	picodev->send = pico_adapter_send;
+	picodev->poll = pico_adapter_poll;
+	picodev->destroy = pico_adapter_destroy;
+
+	pif->edev = edev;
+	edev->picodev = picodev;
+
+	pr_info("Device %s created.\n", picodev->name);
+}
+#endif /* CONFIG_NET_PICO_SUPPORT_ETH */
+
 int eth_register(struct eth_device *edev)
 {
 	struct device_d *dev = &edev->dev;
@@ -388,6 +455,10 @@ int eth_register(struct eth_device *edev)
 	if (!eth_current)
 		eth_current = edev;
 
+#ifdef CONFIG_NET_PICO_SUPPORT_ETH
+	pico_adapter_init(edev);
+#endif
+
 	return 0;
 }
 
diff --git a/net/net.c b/net/net.c
index 23a9173..f4481f8 100644
--- a/net/net.c
+++ b/net/net.c
@@ -194,9 +194,15 @@ static int arp_request(IPaddr_t dest, unsigned char *ether)
 	return 0;
 }
 
+#include <pico_stack.h>
+
 void net_poll(void)
 {
-	eth_rx();
+	if (IS_ENABLED(CONFIG_NET_LEGACY)) {
+		eth_rx();
+	} else if (IS_ENABLED(CONFIG_NET_PICOTCP)) {
+		pico_stack_tick();
+	}
 }
 
 static uint16_t net_udp_new_localport(void)
@@ -262,6 +268,17 @@ static struct net_connection *net_new(IPaddr_t dest, void *handler,
 	struct net_connection *con;
 	int ret;
 
+	if (IS_ENABLED(CONFIG_NET_PICOTCP)) {
+		con = xzalloc(sizeof(*con));
+		con->handler = handler;
+		con->packet = net_alloc_packet();
+		memset(con->packet, 0, PKTSIZE);
+
+		list_add_tail(&con->list, &connection_list);
+
+		return con;
+	}
+
 	if (!edev)
 		return ERR_PTR(-ENETDOWN);
 
@@ -316,6 +333,27 @@ out:
 	return ERR_PTR(ret);
 }
 
+#include <pico_socket.h>
+#include <pico_ipv4.h>
+
+static void picotcp_udp_cb(uint16_t ev, struct pico_socket *sock)
+{
+	struct net_connection *con = sock->priv;
+	udp_rx_handler_f *handler = con->handler;
+	int len;
+	union pico_address ep;
+	char *pkt = con->packet;
+
+	if (ev == PICO_SOCK_EV_ERR) {
+		printf(">>>>>> PICO_SOCK_EV_ERR (%d)\n", pico_err);
+		return;
+	}
+
+	len = pico_socket_recvfrom(sock, pkt, UDP_PAYLOAD_SIZE, &ep, &con->remote_port);
+
+	handler(con, pkt, len);
+}
+
 struct net_connection *net_udp_new(IPaddr_t dest, uint16_t dport,
 		udp_rx_handler_f *handler, void *ctx)
 {
@@ -324,6 +362,26 @@ struct net_connection *net_udp_new(IPaddr_t dest, uint16_t dport,
 	if (IS_ERR(con))
 		return con;
 
+	if (IS_ENABLED(CONFIG_NET_PICOTCP)) {
+		union pico_address remote_address;
+
+		remote_address.ip4.addr = dest;
+
+		con->sock = pico_socket_open(PICO_PROTO_IPV4,
+						PICO_PROTO_UDP, picotcp_udp_cb);
+
+		if (!con->sock)
+			return ERR_PTR(-ENOBUFS);
+
+		/* FIXME: check return value */
+		pico_socket_connect(con->sock, &remote_address, htons(dport));
+
+		con->sock->priv = con;
+		con->priv = ctx;
+
+		return con;
+	}
+
 	con->proto = IPPROTO_UDP;
 	con->udp->uh_dport = htons(dport);
 	con->udp->uh_sport = htons(net_udp_new_localport());
@@ -348,6 +406,10 @@ struct net_connection *net_icmp_new(IPaddr_t dest, rx_handler_f *handler,
 
 void net_unregister(struct net_connection *con)
 {
+	if (IS_ENABLED(CONFIG_NET_PICOTCP)) {
+		pico_socket_close(con->sock);
+	}
+
 	list_del(&con->list);
 	free(con->packet);
 	free(con);
@@ -365,6 +427,13 @@ static int net_ip_send(struct net_connection *con, int len)
 
 int net_udp_send(struct net_connection *con, char *payload, int len)
 {
+	if (IS_ENABLED(CONFIG_NET_PICOTCP)) {
+		/* FIXME: pico_socket_send() ret code is ignored */
+		pico_socket_send(con->sock, payload, len);
+
+		return 0;
+	}
+
 	con->udp->uh_ulen = htons(len + 8);
 	con->udp->uh_sum = 0;
 
@@ -544,12 +613,22 @@ bad:
 	return 0;
 }
 
+#include <pico_stack.h>
+
 int net_receive(struct eth_device *edev, unsigned char *pkt, int len)
 {
 	struct ethernet *et = (struct ethernet *)pkt;
 	int et_protlen = ntohs(et->et_protlen);
 	int ret;
 
+	if (IS_ENABLED(CONFIG_NET_PICOTCP)) {
+		pico_stack_recv(edev->picodev, pkt, len);
+
+		led_trigger_network(LED_TRIGGER_NET_RX);
+
+		return 0;
+	}
+
 	led_trigger_network(LED_TRIGGER_NET_RX);
 
 	if (len < ETHER_HDR_SIZE) {
diff --git a/net/picotcp.c b/net/picotcp.c
new file mode 100644
index 0000000..ee16a68
--- /dev/null
+++ b/net/picotcp.c
@@ -0,0 +1,20 @@
+#include <init.h>
+#include <poller.h>
+#include <pico_stack.h>
+
+static struct poller_struct picotcp_poller;
+
+static void picotcp_poller_cb(struct poller_struct *poller)
+{
+	pico_stack_tick();
+}
+
+static int picotcp_net_init(void)
+{
+	pico_stack_init();
+
+	picotcp_poller.func = picotcp_poller_cb;
+
+	return poller_register(&picotcp_poller);
+}
+postcore_initcall(picotcp_net_init);
-- 
2.1.4




More information about the barebox mailing list