Daniele Lacamera / PicoTCP Featured

Dependents:   lpc1768-picotcp-demo ZeroMQ_PicoTCP_Publisher_demo TCPSocket_HelloWorld_PicoTCP Pico_TCP_UDP_Test ... more

PicoTCP. Copyright (c) 2013 TASS Belgium NV.

Released under the GNU General Public License, version 2.

Different licensing models may exist, at the sole discretion of the Copyright holders.

Official homepage: http://www.picotcp.com

Bug tracker: https://github.com/tass-belgium/picotcp/issues

Development steps:

  • initial integration with mbed RTOS
  • generic mbed Ethernet driver
  • high performance NXP LPC1768 specific Ethernet driver
  • Multi-threading support for mbed RTOS
  • Berkeley sockets and integration with the New Socket API
  • Fork of the apps running on top of the New Socket API
  • Scheduling optimizations
  • Debugging/benchmarking/testing

Demo application (measuring TCP sender performance):

Import programlpc1768-picotcp-demo

A PicoTCP demo app testing the ethernet throughput on the lpc1768 mbed board.

Revision:
149:5f4cb161cec3
Child:
152:a3d286bf94e5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/pico_socket_udp.c	Wed Apr 09 14:31:41 2014 +0200
@@ -0,0 +1,182 @@
+#include <stdint.h>
+#include "pico_socket.h"
+#include "pico_udp.h"
+#include "pico_socket_multicast.h"
+#include "pico_ipv4.h"
+#include "pico_ipv6.h"
+
+#define UDP_FRAME_OVERHEAD (sizeof(struct pico_frame))
+
+
+struct pico_socket *pico_socket_udp_open(void)
+{
+    struct pico_socket *s = NULL;
+#ifdef PICO_SUPPORT_UDP
+    s = pico_udp_open();
+    if (!s) {
+        pico_err = PICO_ERR_ENOMEM;
+        return NULL;
+    }
+
+    s->proto = &pico_proto_udp;
+    s->q_in.overhead = s->q_out.overhead = UDP_FRAME_OVERHEAD;
+#endif
+    return s;
+}
+
+
+#ifdef PICO_SUPPORT_IPV4
+static int pico_socket_udp_deliver_ipv4(struct pico_socket *s, struct pico_frame *f)
+{
+    struct pico_ip4 s_local, p_dst;
+    struct pico_ipv4_hdr *ip4hdr;
+    struct pico_frame *cpy;
+    ip4hdr = (struct pico_ipv4_hdr*)(f->net_hdr);
+    s_local.addr = s->local_addr.ip4.addr;
+    p_dst.addr = ip4hdr->dst.addr;
+    if ((pico_ipv4_is_broadcast(p_dst.addr)) || pico_ipv4_is_multicast(p_dst.addr)) {
+        struct pico_device *dev = pico_ipv4_link_find(&s->local_addr.ip4);
+        if (pico_ipv4_is_multicast(p_dst.addr) && (pico_socket_mcast_filter(s, (union pico_address *)&ip4hdr->dst, (union pico_address *)&ip4hdr->src) < 0))
+            return -1;
+
+        if ((s_local.addr == PICO_IPV4_INADDR_ANY) || /* If our local ip is ANY, or.. */
+            (dev == f->dev)) { /* the source of the bcast packet is a neighbor... */
+            cpy = pico_frame_copy(f);
+            if (!cpy)
+                return -1;
+
+            if (pico_enqueue(&s->q_in, cpy) > 0) {
+                if (s->wakeup)
+                    s->wakeup(PICO_SOCK_EV_RD, s);
+            }
+            else
+                pico_frame_discard(cpy);
+
+        }
+    } else if ((s_local.addr == PICO_IPV4_INADDR_ANY) || (s_local.addr == p_dst.addr))
+    { /* Either local socket is ANY, or matches dst */
+        cpy = pico_frame_copy(f);
+        if (!cpy)
+            return -1;
+
+        if (pico_enqueue(&s->q_in, cpy) > 0) {
+            if (s->wakeup)
+                s->wakeup(PICO_SOCK_EV_RD, s);
+        } else {
+            pico_frame_discard(cpy);
+        }
+    }
+
+    pico_frame_discard(f);
+    return 0;
+}
+#endif
+
+#ifdef PICO_SUPPORT_IPV6
+static int pico_socket_udp_deliver_ipv6(struct pico_socket *s, struct pico_frame *f)
+{
+    struct pico_ip6 s_local, p_dst;
+    struct pico_ipv6_hdr *ip6hdr;
+    struct pico_frame *cpy;
+    ip6hdr = (struct pico_ipv6_hdr*)(f->net_hdr);
+    s_local = s->local_addr.ip6;
+    p_dst = ip6hdr->dst;
+    if ((pico_ipv6_is_multicast(p_dst.addr))) {
+        cpy = pico_frame_copy(f);
+        if (!cpy)
+            return -1;
+
+        if (pico_enqueue(&s->q_in, cpy) > 0) {
+            if (s->wakeup)
+                s->wakeup(PICO_SOCK_EV_RD, s);
+        }
+        else
+            pico_frame_discard(cpy);
+    } else if (pico_ipv6_is_unspecified(s->local_addr.ip6.addr) || (pico_ipv6_compare(&s_local, &p_dst) == 0))
+    { /* Either local socket is ANY, or matches dst */
+        cpy = pico_frame_copy(f);
+        if (!cpy)
+            return -1;
+
+        if (pico_enqueue(&s->q_in, cpy) > 0) {
+            if (s->wakeup)
+                s->wakeup(PICO_SOCK_EV_RD, s);
+        }
+    }
+
+    pico_frame_discard(f);
+    return 0;
+}
+#endif
+
+
+int pico_socket_udp_deliver(struct pico_sockport *sp, struct pico_frame *f)
+{
+    struct pico_tree_node *index = NULL;
+    struct pico_tree_node *_tmp;
+    struct pico_socket *s = NULL;
+    pico_err = PICO_ERR_EPROTONOSUPPORT;
+    #ifdef PICO_SUPPORT_UDP
+    pico_err = PICO_ERR_NOERR;
+    pico_tree_foreach_safe(index, &sp->socks, _tmp){
+        s = index->keyValue;
+        if (IS_IPV4(f)) { /* IPV4 */
+#ifdef PICO_SUPPORT_IPV4
+            return pico_socket_udp_deliver_ipv4(s, f);
+#endif
+        } else {
+#ifdef PICO_SUPPORT_IPV6
+            return pico_socket_udp_deliver_ipv6(s, f);
+#endif
+        }
+    } /* FOREACH */
+    pico_frame_discard(f);
+    if (s)
+        return 0;
+
+    pico_err = PICO_ERR_ENXIO;
+  #endif
+    return -1;
+}
+
+int pico_setsockopt_udp(struct pico_socket *s, int option, void *value)
+{
+    switch(option) {
+    case PICO_SOCKET_OPT_RCVBUF:
+        s->q_in.max_size = (*(uint32_t*)value);
+        return 0;
+    case PICO_SOCKET_OPT_SNDBUF:
+        s->q_out.max_size = (*(uint32_t*)value);
+        return 0;
+    }
+
+    /* switch's default */
+#ifdef PICO_SUPPORT_MCAST
+    return pico_setsockopt_mcast(s, option, value);
+#else
+    pico_err = PICO_ERR_EINVAL;
+    return -1;
+#endif
+}
+
+int pico_getsockopt_udp(struct pico_socket *s, int option, void *value)
+{
+    uint32_t *val = (uint32_t *)value;
+    switch(option) {
+    case PICO_SOCKET_OPT_RCVBUF:
+        *val = s->q_in.max_size;
+        return 0;
+    case PICO_SOCKET_OPT_SNDBUF:
+        *val = s->q_out.max_size;
+        return 0;
+    }
+
+    /* switch's default */
+#ifdef PICO_SUPPORT_MCAST
+    return pico_getsockopt_mcast(s, option, value);
+#else
+    pico_err = PICO_ERR_EINVAL;
+    return -1;
+#endif
+}
+