ovs流表


流表分為兩大類:

1、 內核中flow table 也稱為fast path

2、找用戶態中flow table被稱為slow path

一個數據報文接收后,會經過多個流表,每個流表負責特定的功能,
ovs中的多級流表存放在用戶空間,內核態存放的是流表的緩存。

網卡收到報文時,Openvswitch.ko是這么處理數據報文的: 

1、通過key查找內核中的flow table,得到action,然后執行action之后,直接發送這個包;

2、在內核無法查找到流表項的時候,通過netlink的方式發送到用戶空間,接着會去查找用戶態的流表。 真個過程是通過upcall來調用用戶態ovs-vswtichd中的flow table實現的

3、如果用戶態命中則將對應的信息丟給內核態進行緩存。用戶空間沒有查到,用戶態還要繼續將報文的信息丟給控制器,由控制器下發對應的規則

key的組成

MAC層的key :key->eth

網絡層的key:key->ip

傳輸層的key:key->tp

 

流表發送
流表下發一般是通過以下兩種方式:
controller通過openflow協議下發FLOW_MOD命令給ovs的Userspace流表。
ovs-ofctl通過openflow協議下發FLOW_MOD給ovs的Userspace流表。ovs-ofctl add-flow最終調用 ofctl_flow_mod(ctx->argc, ctx->argv, OFPFC_ADD);
ofctl_flow_mod
   handle_openflow
        handle_flow_mod

 

ovs-vsctl add-port br0 eth1實現

linux 中調用ip link set eht1 master br0會調用netdev_rx_handler_register注冊溝子函數,這樣當網卡收到報文時,會走鈎子函數

 

struct netdev_vport {
struct rcu_head rcu;
struct net_device *dev;
};
const struct vport_ops ovs_netdev_vport_ops = {
.create = netdev_create,
.send = netdev_send,
};
--datapath/vport-netdev.c
static struct vport *netdev_create(const struct vport_parms *parms)
{
struct vport *vport;
struct netdev_vport *netdev_vport;
vport = ovs_vport_alloc(sizeof(struct netdev_vport), &ovs_netdev_vport_ops, parms);
netdev_vport = netdev_vport_priv(vport);
netdev_vport->dev = dev_get_by_name(ovs_dp_get_net(vport->dp), parms->name);
//通過interface name比如eth0 得到eht0 net_device 結構體

err = netdev_rx_handler_register(netdev_vport->dev, netdev_frame_hook, vport);
//核心,收到packet后會調用 netdev_frame_hook處理;
dev_set_promiscuity(netdev_vport->dev, 1); //設置為混雜模式;
return vport;
}

 

netdev_frame_hook最終會調用ovs_dp_process_packet, ovs_dp_process_packet是一個非常重要的函數

 

 用戶態處理流表

內核差找不到失敗時會通過upcall來調用用戶態ovs-vswtichd中的flow table,

用戶態找到找到rule之后,會通過handle_upcalls將flow rule添加到內核中的datapath

handle_upcalls


     dpif_operate


                dpif->dpif_class->operate(dpif, ops, chunk);

 

                          dpif_netlink_operate()會調用netlink修改內核中datapath的規則。

ovs system接口類型 

當接口類型為system時,vport->ops->send函數為netdev_send

/*此函數即為OVS流表output action 發送數據包時的函數*/
static int
netdev_send(struct vport *vport, struct sk_buff *skb)
{
struct netdev_vport *netdev_vport = netdev_vport_priv(vport);
int mtu = netdev_vport->dev->mtu;
int len;
/*如果未開啟gso且數據包長度大於MTU,則釋放數據包*/
if (unlikely(packet_length(skb) > mtu && !skb_is_gso(skb))) {
net_warn_ratelimited("%s: dropped over-mtu packet: %d > %d\n",
netdev_vport->dev->name,
packet_length(skb), mtu);
goto drop;
}
/*設置skb->dev為output action網口*/
skb->dev = netdev_vport->dev;
len = skb->len;
/*最后調用dev_queue_xmit發送數據包*/
dev_queue_xmit(skb);
return len;
drop:
kfree_skb(skb);
return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM