发包处理函数最终会调用到ovs_vport_send函数,该函数最终会调用vport_ops的send函数。
1、ovs_vport_send函数
void ovs_vport_send(struct vport *vport, struct sk_buff *skb)
{
int mtu = vport->dev->mtu;
if (unlikely(packet_length(skb) > mtu && !skb_is_gso(skb))) {
net_warn_ratelimited("%s: dropped over-mtu packet: %d > %d\n",
vport->dev->name,
packet_length(skb), mtu);
vport->dev->stats.tx_errors++;
goto drop;
}
skb->dev = vport->dev; //vport关联的设备,vxlan端口的设备为vxlan_4789
vport->ops->send(skb);<span style="white-space:pre"> </span>//实际调用ovs_vxlan_netdev_vport_ops的vxlan_xmit函数
return;
drop:
kfree_skb(skb);
}
2、vxlan_xmit函数
#define vxlan_xmit rpl_vxlan_xmit<span style="white-space:pre"> </span>//在3.18内核中,OVS还是使用自己的vxlan实现
netdev_tx_t rpl_vxlan_xmit(struct sk_buff *skb)
{
struct net_device *dev = skb->dev;<span style="white-space:pre"> </span>//ovs_vport_send函数中完成设置
struct vxlan_dev *vxlan = netdev_priv(dev);<span style="white-space:pre"> </span>//该信息在创建vxlan端口对应的net_device时就初始化了
const struct ip_tunnel_info *info;
info = skb_tunnel_info(skb); //得到tunnel信息,即execute_set_action函数设置的内容
skb_reset_mac_header(skb);
if ((vxlan->flags & VXLAN_F_PROXY))<span style="white-space:pre"> </span>//当前没有此标记
goto out;
if (vxlan->flags & VXLAN_F_COLLECT_METADATA &&
info && info->mode & IP_TUNNEL_INFO_TX) {
vxlan_xmit_one(skb, dev, NULL, false);<span style="white-space:pre"> </span>//发送报文
return NETDEV_TX_OK;
}
out:
pr_warn("vxlan: unsupported flag set %x", vxlan->flags);
kfree_skb(skb);
return NETDEV_TX_OK;
}
3、vxlan_xmit_one函数
static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
struct vxlan_rdst *rdst, bool did_rsc)
{
struct ip_tunnel_info *info;
struct vxlan_dev *vxlan = netdev_priv(dev);
struct sock *sk = vxlan->vn_sock->sock->sk;
unsigned short family = vxlan_get_sk_family(vxlan->vn_sock); //通过sock判断是IPV4还是IPV6
struct rtable *rt = NULL;
const struct iphdr *old_iph;
struct flowi4 fl4;
union vxlan_addr *dst;
union vxlan_addr remote_ip;
struct vxlan_metadata _md;
struct vxlan_metadata *md = &_md;
__be16 src_port = 0, dst_port;
u32 vni;
__be16 df = 0;
__u8 tos, ttl;
int err;
u32 flags = vxlan->flags;
info = skb_tunnel_info(skb); //从skb中获取tunnel info
if (rdst) { //不进入此分支
dst_port = rdst->remote_port ? rdst->remote_port : vxlan->cfg.dst_port;
vni = rdst->remote_vni;
dst = &rdst->remote_ip;
} else {
if (!info) { //说明当前实现,对于报文从