Permalink
Browse files

Implement sending packets from Mirage, and add some basic test applic…

…ations.
  • Loading branch information...
1 parent 9721886 commit a51477bb5e1c60fd34efbf211d153a46093ec4ba @pgj committed Aug 30, 2012
@@ -41,6 +41,7 @@ external get_vifs: unit -> id list = "caml_get_vifs"
external plug_vif: id -> bool * int * string = "caml_plug_vif"
external unplug_vif: id -> unit = "caml_unplug_vif"
external get_mbufs : int -> Io_page.t list = "caml_get_mbufs"
+external put_mbufs : int -> Io_page.t list -> unit = "caml_put_mbufs"
let devices : (id, t) Hashtbl.t = Hashtbl.create 1
@@ -81,13 +82,11 @@ let create f =
f id t) ids in
th <?> pt
-let write ifc page =
- Console.log (sprintf "Netif.write %s: not implemented yet" ifc.backend);
+let writev ifc bufs =
+ put_mbufs (ifc.backend_id) bufs;
return ()
-let writev ifc pages =
- Console.log (sprintf "Netif.writev %s: not implemented yet" ifc.backend);
- return ()
+let write ifc buf = writev ifc [buf]
let rx_poll ifc fn =
let mbufs = get_mbufs ifc.backend_id in
@@ -41,7 +41,7 @@
#include <net/if_dl.h>
#include <net/if_types.h>
#include <net/if_arp.h>
-#include <net/vnet.h>
+#include <net/ethernet.h>
#include "caml/mlvalues.h"
#include "caml/memory.h"
@@ -56,6 +56,7 @@ struct mbuf_entry {
struct plugged_if {
TAILQ_ENTRY(plugged_if) pi_next;
+ struct ifnet *pi_ifp;
u_short pi_index;
u_short pi_llindex;
int pi_flags;
@@ -76,6 +77,7 @@ CAMLprim value caml_get_vifs(value v_unit);
CAMLprim value caml_plug_vif(value id);
CAMLprim value caml_unplug_vif(value id);
CAMLprim value caml_get_mbufs(value id);
+CAMLprim value caml_put_mbufs(value id, value bufs);
void netif_ether_input(struct ifnet *ifp, struct mbuf **mp);
int netif_ether_output(struct ifnet *ifp, struct mbuf **mp);
@@ -150,7 +152,7 @@ caml_plug_vif(value id)
pip = malloc(sizeof(struct plugged_if), M_MIRAGE, M_NOWAIT | M_ZERO);
if (pip == NULL)
- caml_failwith("Out of memory");
+ caml_failwith("No memory for plugging a new interface");
found = 0;
IFNET_WLOCK();
@@ -159,6 +161,7 @@ caml_plug_vif(value id)
if (strncmp(ifp->if_xname, String_val(id), IFNAMSIZ) == 0) {
/* "Enable" the fake NetGraph node. */
IFP2AC(ifp)->ac_netgraph = (void *) 1;
+ pip->pi_ifp = ifp;
pip->pi_index = ifp->if_index;
pip->pi_flags = ifp->if_flags;
bcopy(ifp->if_xname, pip->pi_xname, IFNAMSIZ);
@@ -227,7 +230,8 @@ caml_unplug_vif(value id)
}
IFNET_WUNLOCK();
- mtx_lock(&pip->pi_rx_lock);
+ TAILQ_REMOVE(&pihead, pip, pi_next);
+
e1 = LIST_FIRST(&pip->pi_rx_head);
while (e1 != NULL) {
e2 = LIST_NEXT(e1, me_next);
@@ -236,10 +240,8 @@ caml_unplug_vif(value id)
e1 = e2;
}
LIST_INIT(&pip->pi_rx_head);
- mtx_unlock(&pip->pi_rx_lock);
-
- TAILQ_REMOVE(&pihead, pip, pi_next);
mtx_destroy(&pip->pi_rx_lock);
+
free(pip, M_MIRAGE);
plugged--;
@@ -313,12 +315,110 @@ caml_get_mbufs(value id)
CAMLreturn(result);
}
-/* Generating outgoing Ethernet data. */
+/* This function is intentionally left blank. */
int
netif_ether_output(struct ifnet *ifp, struct mbuf **mp)
{
- if (plugged == 0)
- return 0;
-
return 0;
}
+
+static void
+netif_mbuf_free(void *p1, void *p2)
+{
+ u_int *u = (u_int *) p1;
+
+ /* u[0]: refcount */
+ if (--u[0] == 0) {
+ /* u[1]: data_size */
+ contigfree(p2, u[1], M_MIRAGE);
+ free(u, M_MIRAGE);
+ }
+}
+
+static struct mbuf *
+netif_map_to_mbuf(void *data, u_int *u)
+{
+ struct mbuf **mp;
+ struct mbuf *m;
+ struct mbuf *frag;
+ size_t frag_len;
+ char *p;
+
+ frag_len = u[1];
+ mp = &frag;
+ p = data;
+
+ while (frag_len > 0) {
+ MGET(m, M_DONTWAIT, MT_DATA);
+ if (m != NULL) {
+ m->m_flags |= M_EXT;
+ m->m_ext.ext_type = EXT_EXTREF;
+ m->m_ext.ext_buf = (void *) p;
+ m->m_ext.ext_free = netif_mbuf_free;
+ m->m_ext.ext_arg1 = u;
+ m->m_ext.ext_arg2 = data;
+ m->m_ext.ref_cnt = &u[0];
+ m->m_len = min(MCLBYTES, frag_len);
+ m->m_data = m->m_ext.ext_buf;
+ *(m->m_ext.ref_cnt) += 1;
+ } else {
+ m_freem(frag);
+ return NULL;
+ }
+ frag_len -= m->m_len;
+ p += m->m_len;
+ *mp = m;
+ mp = &(m->m_next);
+ }
+
+ return frag;
+}
+
+CAMLprim value
+caml_put_mbufs(value id, value bufs)
+{
+ CAMLparam2(id, bufs);
+ CAMLlocal1(v);
+ struct plugged_if *pip;
+ struct mbuf **mp;
+ struct mbuf *frag;
+ struct mbuf *pkt;
+ struct caml_ba_array *b;
+ u_int *u;
+ size_t pkt_len;
+
+ if ((bufs == Val_emptylist) || (plugged == 0))
+ CAMLreturn(Val_unit);
+
+ pip = find_pi_by_index(Int_val(id));
+ if (pip == NULL)
+ CAMLreturn(Val_unit);
+
+ pkt_len = 0;
+ mp = &pkt;
+
+ while (bufs != Val_emptylist) {
+ v = Field(bufs, 0);
+ b = Caml_ba_array_val(v);
+ u = (u_int *) b->data2;
+ frag = netif_map_to_mbuf(b->data, u);
+ if (frag == NULL)
+ caml_failwith("No memory for mapping to mbuf");
+ *mp = frag;
+ mp = &(frag->m_next);
+ pkt_len += u[1];
+ bufs = Field(bufs, 1);
+ }
+
+ pkt->m_flags |= M_PKTHDR;
+ pkt->m_pkthdr.len = pkt_len;
+ pkt->m_pkthdr.rcvif = NULL;
+ SLIST_INIT(&pkt->m_pkthdr.tags);
+
+ if (pkt->m_pkthdr.len > pip->pi_ifp->if_mtu)
+ printf("%s: Packet is greater (%d) than the MTU (%ld)\n",
+ pip->pi_xname, pkt->m_pkthdr.len, pip->pi_ifp->if_mtu);
+
+ ether_output_frame(pip->pi_ifp, pkt);
+ CAMLreturn(Val_unit);
+}
@@ -82,7 +82,7 @@ struct caml_ba_proxy {
struct caml_ba_array {
void * data; /* Pointer to raw data */
#ifdef _KERNEL
- struct mbuf * m; /* Encapsulating mbuf(9) or NULL */
+ void * data2; /* Interoperating with mbuf(9) or NULL */
#endif
intnat num_dims; /* Number of dimensions */
intnat flags; /* Kind of element array + memory layout + allocation status */
@@ -204,6 +204,9 @@ caml_ba_alloc(int flags, int num_dims, void * data, intnat * dim)
value res;
struct caml_ba_array * b;
intnat dimcopy[CAML_BA_MAX_NUM_DIMS];
+#ifdef _KERNEL
+ u_int *u;
+#endif
Assert(num_dims >= 1 && num_dims <= CAML_BA_MAX_NUM_DIMS);
Assert((flags & CAML_BA_KIND_MASK) <= CAML_BA_COMPLEX64);
@@ -230,12 +233,17 @@ caml_ba_alloc(int flags, int num_dims, void * data, intnat * dim)
b = Caml_ba_array_val(res);
#ifdef _KERNEL
if ((flags & CAML_BA_MANAGED_MASK) == CAML_BA_MBUF) {
- b->m = (struct mbuf *) data;
- b->data = mtod(b->m, void *);
+ b->data2 = data;
+ b->data = mtod((struct mbuf *) b->data2, void *);
}
else {
- b->m = NULL;
- b->data = data;
+ b->data = data;
+ b->data2 = __malloc(2 * sizeof(u_int));
+ if (b->data2 == NULL) caml_raise_out_of_memory();
+ u = (u_int *) b->data2;
+ for (u[1] = 0, i = 0; i < num_dims; i++)
+ u[1] += dim[i];
+ u[0] = 1;
}
#else
b->data = data;
@@ -587,19 +595,22 @@ static void caml_ba_finalize(value v)
{
struct caml_ba_array * b = Caml_ba_array_val(v);
#ifdef _KERNEL
- int data_size, i;
+ u_int *u;
#endif
switch (b->flags & CAML_BA_MANAGED_MASK) {
case CAML_BA_EXTERNAL:
break;
case CAML_BA_MANAGED:
+#ifdef _KERNEL
+ u = (u_int *) b->data2;
+#endif
if (b->proxy == NULL) {
#ifdef _KERNEL
- data_size = 0;
- for (i = 0; i < b->num_dims; i++)
- data_size += b->dim[i];
- contigfree(b->data, data_size, M_MIRAGE);
+ if (--u[0] == 0) {
+ contigfree(b->data, u[1], M_MIRAGE);
+ __free(u);
+ }
#else
free(b->data);
#endif
@@ -608,7 +619,10 @@ static void caml_ba_finalize(value v)
(int) b->proxy->refcount, 0, 0, 0);
if (-- b->proxy->refcount == 0) {
#ifdef _KERNEL
- contigfree(b->proxy->data, b->proxy->size, M_MIRAGE);
+ if (--u[0] == 0) {
+ contigfree(b->proxy->data, b->proxy->size, M_MIRAGE);
+ __free(u);
+ }
#else
free(b->proxy->data);
#endif
@@ -621,7 +635,7 @@ static void caml_ba_finalize(value v)
break;
#ifdef _KERNEL
case CAML_BA_MBUF:
- m_free(b->m);
+ m_free((struct mbuf *) b->data2);
break;
#endif
}
@@ -961,8 +975,20 @@ static void caml_ba_update_proxy(struct caml_ba_array * b1,
struct caml_ba_array * b2)
{
struct caml_ba_proxy * proxy;
+#ifdef _KERNEL
+ u_int *u;
+ int i;
+#endif
/* Nothing to do for un-managed arrays */
if ((b1->flags & CAML_BA_MANAGED_MASK) == CAML_BA_EXTERNAL) return;
+#ifdef _KERNEL
+ /* Update size information */
+ if ((b2->flags & CAML_BA_MANAGED_MASK) != CAML_BA_MBUF) {
+ u = (u_int *) b2->data2;
+ for (u[1] = 0, i = 0; i < b2->num_dims; i++)
+ u[1] += b2->dim[i];
+ }
+#endif
if (b1->proxy != NULL) {
/* If b1 is already a proxy for a larger array, increment refcount of
proxy */
@@ -23,6 +23,16 @@ basic/netif:
echo "let _ = OS.Main.run (Netif.main ())" > main.ml
${MAKE} -f Makefile.kmod SRCS=netif.ml KMOD=mirage-basic-netif
+basic/arp:
+ ln -sf basic/arp.ml .
+ echo "let _ = OS.Main.run (Arp.main ())" > main.ml
+ ${MAKE} -f Makefile.kmod SRCS=arp.ml KMOD=mirage-basic-arp
+
+basic/ping:
+ ln -sf basic/ping.ml .
+ echo "let _ = OS.Main.run (Ping.main ())" > main.ml
+ ${MAKE} -f Makefile.kmod SRCS=ping.ml KMOD=mirage-basic-ping
+
basic/sleep:
ln -sf basic/sleep.ml .
echo "let _ = OS.Main.run (Sleep.main ())" > main.ml

0 comments on commit a51477b

Please sign in to comment.