我有一些机器在同一个网络上运行。一个节点是控制节点,它将流向它的流量分配给其他节点。问题是我想在MAC头和输入到控制节点的IP(或其他)有效载荷之间有一个自定义协议头。
控制节点收到这样的任何数据包:
------------------------------------------------
| Layer 2 | IP(or whatever protocol) | Payload |
------------------------------------------------
此数据包应该像这样分发给其他节点
----------------------------------------------------------------
| Layer 2 | Custom Header | IP(or whatever protocol) | Payload |
----------------------------------------------------------------
我想要一些方向来做这样的事情,有没有我可以使用的当前解决方案,我必须从头开始破解内核。类似的方法是使用L2TP,但是在IP层上运行,所以我不想要它。
我还希望这个通信在linux中作为一个单独的接口出现,就像tun0而不是物理eth0接口。
任何帮助或想法都将受到高度赞赏。
我不知道这个问题属于哪个堆栈交换网站,所以也非常感谢正确网站的指示。
答案 0 :(得分:2)
您的情况与VLAN非常相似,其中VLAN标头也位于L2标头和IP标头之间。您可以查看VLAN代码,尤其是net / 8021q / vlan_dev.c。
这里的关键是你需要构建自己的L2头,所以你需要注册自己的header_ops,就像VLAN一样:
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;
}