Skip to the content.

移植说明

链路层分析

输入输出接口实现

链路层分析

struct ifnet ifp;
uint8_t lla[ETHER_ADDR_LEN];

void ether_ifattach(struct ifnet *ifp, const u_int8_t *lla);

接收实现

参考f-stack实现

static void
ff_veth_init(void *arg)
{
    struct ff_veth_softc *sc = arg;
    struct ifnet *ifp = sc->ifp;

    ifp->if_drv_flags |= IFF_DRV_RUNNING;
    ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
}

static int
ff_veth_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
    int error = 0;
    struct ff_veth_softc *sc = ifp->if_softc;

    switch (cmd) {
    case SIOCSIFFLAGS:
        if (ifp->if_flags & IFF_UP) {
            ff_veth_init(sc);
        } else if (ifp->if_drv_flags & IFF_DRV_RUNNING)
            ff_veth_stop(sc);
        break;
    default:
        error = ether_ioctl(ifp, cmd, data);
        break;
    }

    return (error);
}

static int
ff_veth_transmit(struct ifnet *ifp, struct mbuf *m)
{
    struct ff_veth_softc *sc = (struct ff_veth_softc *)ifp->if_softc;
    return ff_dpdk_if_send(sc->host_ctx, (void*)m, m->m_pkthdr.len);
}

static void
ff_veth_qflush(struct ifnet *ifp)
{

}

void demo_veth_set_interface()
{
     struct ifnet *ifp;

    ifp = sc->ifp = if_alloc(IFT_ETHER);

    ifp->if_init = ff_veth_init;
    ifp->if_softc = sc;

    if_initname(ifp, sc->host_ifname, IF_DUNIT_NONE);
    ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
    ifp->if_ioctl = ff_veth_ioctl;
    ifp->if_start = ff_veth_start;
    ifp->if_transmit = ff_veth_transmit;
    ifp->if_qflush = ff_veth_qflush;
    ether_ifattach(ifp, sc->mac);
}

发送实现

void
ff_veth_process_packet(void *arg, void *m)
{
    struct ifnet *ifp = (struct ifnet *)arg;
    struct mbuf *mb = (struct mbuf *)m;

    mb->m_pkthdr.rcvif = ifp;

    ifp->if_input(ifp, mb);
}

需要注册一个ifnet结构体与mac地址到ether_ifattach

仿真程序

SOCKET RAW

// socket
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>

int socket(int domain, int type, int protocol);

domain | AF_UNIX, 本地通讯: | unix(7) | unix(7) | |—-| —- | — | | AF_INET | IPv4 网络协议 | ip(7)| | AF_INET6 | IPv6 网络协议 | ipv6(7)| | AF_IPX | IPX - Novell 协议 | | | AF_NETLINK | 内核用户界面设备 | netlink(7)| | AF_X25 | ITU-T X.25 / ISO-8208 协议 | x25(7)| | AF_AX25 | Amateur radio AX.25 protocol || | AF_ATMPVC | Access to raw ATM PVCs || | AF_APPLETALK | Appletalk | ddp(7)| | AF_PACKET | 底层包连接 | packet(7)|

type

SOCK_STREAM     提供有序的,可靠的,双向的,基于字节流的通讯。可能支持带外传输。
SOCK_DGRAM      提供数据报(不面向连接的, 不可靠的固定最大长度的信息)。
SOCK_SEQPACKET  提供有序的,可靠的,双向的,基于固定最大长度的数据报传输路径;需要一个读取整个伴有输入系统调用的包的用户。
SOCK_RAW        提供未加工(raw)的网络协议通道。
SOCK_RDM        提供可靠的数据报层,但是不保证顺序。
SOCK_PACKET     废弃的,不应该在新的程序中使用,参考 packet(7)。

SOCK_NONBLOCK   设置 O_NONBLOCK 的标志于新打开的文件描述符
SOCK_CLOEXEC    设置 close-on-exec (FD_CLOEXEC) 的标志于新打开的文件描述符

例子实现

socket(AF_INET, SOCK_RAW, IPPROTO_XXX);     		// 网络层IP数据包
socket(PF_PACKET, SOCK_RAW, htons(ETH_P_XXX));		// 数据链路层数据帧

硬件实现