Daniel G. Waddington <dwaddington@lucent.com> wrote:
: Hi,
: I know I’m a bit head of the documentation release for QRTP device drivers,
: but does anyone know what I should use for the _io_net_registrant parameters
: for a module filtering above an ethernet NIC module. I’m most clueless
: about top_type, bot_type and func_hdl.
: struct _io_net_registrant {
: uint32_t flags;
: char *name;
: char *top_type;
: char *bot_type;
: void *func_hdl;
: io_net_registrant_funcs_t funcs;
: int ndependencies;
: int reserved[2];
: / io_net_dependency_t [ndependencies]; */
: };
: Thanks
: DAN
Here’s a ‘dinky’ pass through filter. func_hdl is just passed to the callouts you
provide. ie it’s a convienent way to be passed a per registrant control struct.
-seanb
dinky.h
struct dinky_control {
int reg_hdl;
io_net_self_t *ion;
dispatch_t *dpp;
uint16_t endpoint;
};
dinky.c
#include <sys/io-net.h>
#include <net/if_ether.h>
#include <errno.h>
#include “dinky.h”
struct dinky_control dinky_ctrl;
int dinky_rx_up(npkt_t *npkt, void *func_hdl, int off, int len_sub, uint16_t cell, uint16_t endpoint, uint16_t iface);
int dinky_rx_down(npkt_t *npkt, void *rx_down_hdl);
int dinky_tx_done(npkt_t *npkt, void *done_hdl, void *func_hdl);
int dinky_shutdown1(int registrant_hdl, void *func_hdl);
int dinky_shutdown2(int registrant_hdl, void *func_hdl);
int dinky_devctl(void *hdl, int dcmd, void *data, size_t size, int *ret);
io_net_registrant_funcs_t dinky_funcs = {
8,
dinky_rx_up,
dinky_rx_down,
dinky_tx_done,
dinky_shutdown1,
dinky_shutdown2,
NULL, //advertise_ifaces
dinky_devctl,
NULL, //flush
NULL //raw_open
};
io_net_registrant_t dinky_reg = {_REG_FILTER_ABOVE, “ncm-dinky.so”, “en”, “en”, &dinky_ctrl, &dinky_funcs, 0};
int dinky_entry(void *dll_hdl, dispatch_t *dpp, io_net_self_t *n, char *options);
/* io-net does a dlsym on “io_net_dll_entry” so don’t change this name */
io_net_dll_entry_t io_net_dll_entry = {
2,
dinky_entry,
NULL
};
int
dinky_entry(void *dll_hdl, dispatch_t *dpp, io_net_self_t *n, char *options)
{
struct dinky_control *dc = &dinky_ctrl;
dc->ion = n;
dc->dpp = dpp;
if(dc->ion->reg(dll_hdl, &dinky_reg, &dc->reg_hdl, NULL, &dc->endpoint) == -1)
{
return -1;
}
/* To receive all up headed packets */
if(dc->ion->reg_byte_pat(dc->reg_hdl, 0, 0, NULL, _BYTE_PAT_ALL) == -1)
{
return -1;
}
return 0;
}
int
dinky_shutdown1(int registrant_hdl, void func_hdl)
{
/ Our last chance for this thread to tx (this thread has exclusive access) */
return 0;
}
int
dinky_shutdown2(int registrant_hdl, void func_hdl)
{
/ We now have shared access. This is where you would do most of your cleanup work */
return 0;
}
int
dinky_rx_down(npkt_t *npkt, void *func_hdl)
{
struct dinky_control *dc = func_hdl;
struct ether_header *eh;
if(npkt->flags & _NPKT_MSG)
{
/*
- It’s a control packet of some sort.
- Pass it on
*/
return dc->ion->tx_down(dc->reg_hdl, npkt);
}
#if 0
if(you_decide_not_to_pass_it_on)
{
dc->ion->tx_done(dc->reg_hdl, npkt);
return TX_DOWN_FAILED;
}
#endif
/*
- arp always puts ethernet header in first buffer. ip stacks fragment thereafter. Of course
- it could be from someone other than ip / arp.
/
eh = (struct ether_header )npkt->buffers.tqh_first->net_iov->iov_base;
/ Do your work here/
/* Then pass it on */
return dc->ion->tx_down(dc->reg_hdl, npkt);
}
int
dinky_rx_up(npkt_t *npkt, void *func_hdl, int off, int len_sub, uint16_t cell, uint16_t endpoint, uint16_t iface)
{
struct dinky_control *dc = func_hdl;
struct ether_header *eh;
if(npkt->flags & _NPKT_MSG)
{
/*
- It’s a control packet of some sort.
- You can learn about interfaces coming and going from below you this way
- (see _IO_NET_MSG_DL_ADVERT and io_net_msg_dl_advert_t in <sys/io-net.h>).
- You have to handle duplicate adverts. You get a npkt->flags & (_NPKT_MSG |_NPKT_MSG_DYING)
- when cell endpoint is going away.
*/
/*
- pass it on.
/
if(dc->ion->tx_up(dc->reg_hdl, npkt, off, len_sub, cell, endpoint, iface) == 0)
{
/ noone above you took it */
dc->ion->tx_done(dc->reg_hdl, npkt);
}
return 0;
}
#if 0
if(you_decide_not_to_pass_it_on)
{
dc->ndi->tx_done(dc->reg_hdl, npkt);
return 0;
}
#endif
/*
- Should check how (if) the packet is fragmented.
*/
eh = (struct ether_header *)npkt->buffers.tqh_first->net_iov->iov_base;
/* Do your work here */
/* Pass it on /
if(dc->ion->tx_up(dc->reg_hdl, npkt, off, len_sub, cell, endpoint, iface) == 0)
{
/ noone above you took it */
dc->ion->tx_done(dc->reg_hdl, npkt);
}
return 0;
}
int
dinky_tx_done(npkt_t *npkt, void *done_hdl, void *func_hdl)
{
struct dinky_control dc = func_hdl;
/
- If you ever call dc->ion->reg_tx_done(dc->reg_hdl, npkt, done_hdl) (ever add something to
- head or tail of down headed packet or ever originate your own up / down packet (don’t think
- a sniffer would ever do this)), this func will be called when the packet is consumed so you
- can undo / reclaim what you did. In this example it should never be called (we never call
- dc->ion->reg_tx_done()).
*/
return 0;
}
int
dinky_devctl(void *hdl, int dcmd, void *data, size_t size, int ret)
{
/
- Any devctl on /dev/io-net/en_enX where X is dc->endpoint (filters can be stacked)
- will pop out here.
*/
return EOPNOTSUPP;
}