0

我有一些机器在同一个网络上运行。一个节点是将到达它的流量分配给其他节点的控制节点。问题是我希望在 MAC 标头和传入控制节点的 IP(或其他)有效负载之间有一个自定义协议标头。

控制节点接收到这样的任何数据包:

------------------------------------------------
| Layer 2 | IP(or whatever protocol) | Payload |
------------------------------------------------

这个数据包应该像这样分发到其他节点

----------------------------------------------------------------
| Layer 2 | Custom Header | IP(or whatever protocol) | Payload |
----------------------------------------------------------------

我想要一些方向来做这样的事情,有没有我可以使用的当前解决方案,我必须从头开始破解内核。一种类似的方法是使用 L2TP,但它在 IP 层上运行,所以我不想要。

我还希望这种通信在 linux 中显示为一个单独的接口,例如 tun0,除了物理 eth0 接口。

任何帮助或想法将不胜感激。

我不知道这个问题属于哪个堆栈交换网站,因此也感谢正确网站的指示。

4

1 回答 1

2

您的情况与 VLAN 非常相似,VLAN 标头也位于 L2 标头和 IP 标头之间。您可以查看 VLAN 代码,尤其是 net/8021q/vlan_dev.c。

这里的关键是您需要构建自己的 L2 标头,因此您需要像 VLAN 一样注册自己的 header_ops:

static const struct header_ops vlan_header_ops = {
        .create  = vlan_dev_hard_header,
        .rebuild = vlan_dev_rebuild_header,
        .parse   = eth_header_parse,
};

并在初始化期间注册它:

dev->header_ops      = &vlan_header_ops;
dev->hard_header_len = real_dev->hard_header_len + VLAN_HLEN;

这里的 ->create() 函数指针用于创建自定义标头:

static int vlan_dev_hard_header(struct sk_buff *skb, struct net_device *dev,
                unsigned short type,
                const void *daddr, const void *saddr,
                unsigned int len)
{
    struct vlan_hdr *vhdr;
    unsigned int vhdrlen = 0;
    u16 vlan_tci = 0;
    int rc;

    if (!(vlan_dev_priv(dev)->flags & VLAN_FLAG_REORDER_HDR)) {
        vhdr = (struct vlan_hdr *) skb_push(skb, VLAN_HLEN);

        vlan_tci = vlan_dev_priv(dev)->vlan_id;
        vlan_tci |= vlan_dev_get_egress_qos_mask(dev, skb);
        vhdr->h_vlan_TCI = htons(vlan_tci);

        /*
         *  Set the protocol type. For a packet of type ETH_P_802_3/2 we
         *  put the length in here instead.
         */
        if (type != ETH_P_802_3 && type != ETH_P_802_2)
            vhdr->h_vlan_encapsulated_proto = htons(type);
        else
            vhdr->h_vlan_encapsulated_proto = htons(len);

        skb->protocol = htons(ETH_P_8021Q);
        type = ETH_P_8021Q;
        vhdrlen = VLAN_HLEN;
    }

    /* Before delegating work to the lower layer, enter our MAC-address */
    if (saddr == NULL)
        saddr = dev->dev_addr;

    /* Now make the underlying real hard header */
    dev = vlan_dev_priv(dev)->real_dev;
    rc = dev_hard_header(skb, dev, type, daddr, saddr, len + vhdrlen);
    if (rc > 0)
        rc += vhdrlen;
    return rc;
}
于 2012-12-09T15:21:32.370 回答