Wednesday, March 19, 2014

OpenVswitch function flow.

Courtesy : http://wangcong.org/blog/archives/2131

My host machine  is ubuntu.  I have started another ubuntu VM using virtmanager.   So i have a interface  virbr0  created on host with  ip address  192.168.122.1  and  guest ubutntu machine is having an ip address of   192.168.122.68.

I   could  ping   guest from  host.
 
host# ping 192.168.122.68 

I started openvswitch using below  commands

sudo ./ovsdb/ovsdb-tool create /usr/local/etc/openvswitch/conf.db vswitchd/vswitch.ovsschema
sudo ./ovsdb/ovsdb-server  --remote=punix:/usr/local/var/
run/openvswitch/db.sock
                                            --remote=unix:/usr/local/var/
run/openvswitch/rat.unix
                                            --remote=tcp:127.0.0.1:32001   --pidfile --detach
sudo ./utilities/ovs-vsctl --no-wait init
sudo ./vswitchd/ovs-vswitchd --pidfile --detach -v --log-file=/tmp/log

I  added  virbr0 to rat-ovs-br0 bridge using below commands
sudo ./utilities/ovs-vsctl add-br rat-ovs-br0
sudo ./utilities/ovs-vsctl add-port  rat-ovs-br0 virbr0
sudo ifconfig virbr0 0.0.0.0 up
sudo ifconfig rat-ovs-br0 192.168.122.1 up

 opevswitch  creates 
 OVS_VPORT_TYPE_NETDEV  vport  for  virbr0 interface
                        &
OVS_VPORT_TYPE_INTERNAL vport for  rat-ovs-br0 interface

 vport  ops functions for virbr0
struct  ovs_netdev_vport_ops   {
         .type = OVS_VPORT_TYPE_NETDEV
         .create =  netdev_create()
         .send   = netdev_send()
}

vport ops functions  for rat-ovs-br0
struct ovs_internal_vport_ops  {
       .type =  OVS_VPORT_TYPE_INTERNAL
       .create = internal_dev_create
        /* internal_dev_create register a new net_device
            with linux kernel. the device ops function of that
            interface are in structure  
            struct internal_dev_netdev_ops
         */ 
       .send  =  internal_dev_send
}

struct  internal_dev_netdev_ops {
  .ndo_open  = internal_dev_open()
  .ndo_start_xmit = internal_dev_xmit()
}







Case  A:  
packet  (  from  host [ 192.168.122.1]  to guest [ 192.168.122.68]   )

usespace
       |
syscall () , send
       |
ip_send_skb
       |
ip_output
       |
dev_queue_xmit                               
       |
dev_hard_start_xmit
       |
internal_dev_xmit
       |
ovs_port_receive         [ Colored are in openvswitch.ko ]
       |
 ovs_dp_process_received_packet
       |                             
       |
flow = ovs-flow-lookup    // this will send  the packet to 
unlikely(!flow) {                //userspace thru netlink socket if
   ovs-dp-upcall(dp, skb)  //flow does not exist for this packet  
}     |
       |                                  
       |                            
       |                         
       |                             //In this scenario, flow exist. so not
       |                             // sending to userspace.
       |
ovs_execute_actions
       | 
do_output        
       |
 ovs_port_send
       |
 netdev_send
       |
dev_queue_xmit            // this will  reinject  the
                                    //packet to qdisc and
                                    // will call  hard_xmit of   virbr0


Case  B:  
packet  (  from  guest[ 192.168.122.68]  to host [ 192.168.122.1]   ) 

do_softirq   
     |
net_rx_action
     |
netif_receive_skb
     |
netdev_frame_hook
     |
netdev_port_receive                                         
     |                                       
ovs_vport_receive            [ openvswith.ko  colored]
     |
ovs_dp_process_received_packet         
     |                                   
flow = ovs-flow-lookup    // this will send  the packet to 
unlikely(!flow) {                //userspace thru netlink socket if
   ovs-dp-upcall(dp, skb)  //flow does not exist for this packet  
 }                                      // in this scenario, flow exist.
     |
ovs_execute_action  
     | 
do_output
     |
ovs_vport_send
     |
vport->ops->send
     |
internal_dev_recv
     |
netif_rx


Case  C:  
packet  (  from  guest[ 192.168.122.68]  to host [ 192.168.122.1]   ; and first packet)


do_softirq   
    |
net_rx_action
    |
netif_receive_skb
    |
netdev_frame_hook
    |
netdev_port_receive                                         
    |                                       
ovs_vport_receive        [ openvswith.ko  ]
    |
ovs_dp_process_received_packet       
    | 
    | 
flow = ovs-flow-lookup    // this will send  the packet to 
unlikely(!flow) {                //userspace thru netlink socket
ovs-dp-upcall(dp, skb)     // since there is no flow
   }     

    



// receiving of same packet  from userpace 
// after ovs daemon analysis

sys-sendmsg
    |
netlink-sendmsg
    |
genl_recv
    |
ovs_packet_cmd_execute
    |
ovs_execute_actions       [ openvswitch.ko ]
    |
do_output
    |
ovs_vport_send
    |
internal_dev_receive
    |
netif_rx