ovs-vsctl add-br br0 會在數據庫裏面加入新bridge的信息
ovs-vsctl add-port br0 eth0 會在數據庫裏面加入新的port信息
void bridge_run(void)
{
//數據庫發生變化
if (ovsdb_idl_get_seqno(idl) != idl_seqno || vlan_splinters_changed) {
idl_seqno = ovsdb_idl_get_seqno(idl);
bridge_reconfigure(cfg ? cfg : &null_cfg);
}
}
struct bridge {
struct hmap_node node; /* In 'all_bridges'. */
char *name; /* User-specified arbitrary name. */
char *type; /* Datapath type. */
uint8_t ea[ETH_ADDR_LEN]; /* Bridge Ethernet Address. */
uint8_t default_ea[ETH_ADDR_LEN]; /* Default MAC. */
const struct ovsrec_bridge *cfg;
/* OpenFlow switch processing. */
struct ofproto *ofproto; /* OpenFlow switch. */
/* Bridge ports. */
struct hmap ports; /* "struct port"s indexed by name. */
struct hmap ifaces; /* "struct iface"s indexed by ofp_port. */
}
ofproto代表一個bridge的open flow proto
struct ofproto {
struct hmap_node hmap_node; /* In global 'all_ofprotos' hmap. */
/*all the operation fcuntion of the ofproto*/
const struct ofproto_class *ofproto_class;
char *type; /* Datapath type. */
char *name;
uint64_t datapath_id; /* Datapath ID. */
struct oftable *tables; /*flow tables*/
int n_tables
struct hmap ports; /* Contains "struct ofport"s. */
/* OpenFlow connections. */
struct connmgr *connmgr;
}
struct ofproto_dpif {
struct hmap_node all_ofproto_dpifs_node; /* In 'all_ofproto_dpifs'. */
struct ofproto up;
struct dpif_backer *backer;/*每個ofproto都有相同的dpif_backer, 它代表整個ovs datapath*/
}
struct dpif_backer {
char *type;
int refcount;
struct dpif *dpif;
}
/*openvswitch datapath的handler, 負責與內核打交道*/
struct dpif {
const struct dpif_class *dpif_class;
}
bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg)
{
/*根據數據庫更新信息添加或者刪除bridge*/
add_del_bridges(ovs_cfg);
/*根據數據庫更新信息爲每個bridge收集新port或者刪除port*/
HMAP_FOR_EACH (br, node, &all_bridges) {
/*如果是增加一個bridge,這裏還會添加一個internal的local port爲新的bridge*/
bridge_collect_wanted_ports(br, splinter_vlans, &br->wanted_ports);
bridge_del_ports(br, &br->wanted_ports);
}
HMAP_FOR_EACH_SAFE (br, next, node, &all_bridges) {
if (!br->ofproto) {
/*
如果是新加的brdige會分配一個ofproto,實際分配oproto_dpif
ofproto = ofproto_dpif_class->alloc
ofproto->ofproto_class = ofproto_dpif_class
會獲取dpif_backer,如果還沒有就通過dp_if_create_and_open函數使用OVS_DP_CMD_NEW創建一個ovs-datapath,生成ovs-system設備
從內核角度看,整個openvswitch系統就是一個datapath.
ofproto->ofproto_class->construct(ofproto)
*/
ofproto_create(br->name, br->type, &br->ofproto);
}
}
HMAP_FOR_EACH (br, node, &all_bridges) {
bridge_add_ports(br, &br->wanted_ports);
shash_destroy(&br->wanted_ports);
}
}
在內核看來用戶態的bridge/datapath都只是整個openvswitch datapath的vport
只是新的bridge的vport是一個internal, add-port的是netdev, gre等
struct iface {
struct list port_elem; /* Element in struct port's "ifaces" list. */
struct hmap_node ofp_port_node; /* In struct bridge's "ifaces" hmap.
struct port *port; /* Containing port. */
struct netdev *netdev; /* Network device. */
ofp_port_t ofp_port; /* OpenFlow port number. */
const struct ovsrec_interface *cfg; /*cfg for interface*/
};
struct port {
struct bridge *bridge;
char *name;
struct hmap_node hmap_node; /* Element in struct bridge's "ports" hmap. */
const struct ovsrec_port *cfg /*cfg for port*/
/* An ordinary bridge port has 1 interface.
* A bridge port for bonding has at least 2 interfaces. */
struct list ifaces; /* List of "struct iface"s. */
};
bridge_add_ports--->iface_create
{
/*create interface*/
iface_do_create(br, iface_cfg, port_cfg, &ofp_port, &netdev);
iface->netdev = netdev;
hmap_insert(&br->ifaces, &iface->ofp_port_node, hash_ofp_port(ofp_port));
/*create port*/
port = port_create(br, port_cfg)
//hmap_insert(&br->ports, &port->hmap_node, hash_string(port->name, 0));
list_push_back(&port->ifaces, &iface->port_elem);
}
struct netdev {
/* The following do not change during the lifetime of a struct netdev. */
char *name; /* Name of network device. */
const struct netdev_class *netdev_class;
}
struct netdev_linux {
struct netdev up;
}
const struct netdev_class netdev_linux_class =
NETDEV_LINUX_CLASS(
"system",
netdev_linux_construct,
netdev_linux_get_stats,
NULL, /* set_stats */
netdev_linux_get_features,
netdev_linux_get_status);
const struct netdev_class netdev_internal_class =
NETDEV_LINUX_CLASS(
"internal",
netdev_linux_construct,
netdev_internal_get_stats,
netdev_internal_set_stats,
NULL, /* get_features */
netdev_internal_get_status);
}
/*gre*/
struct netdev_vport {
struct netdev up;
/* Tunnels. */
struct netdev_tunnel_config tnl_cfg;
};
TUNNEL_CLASS("gre", "gre_system"),
int iface_do_create()
{
/*根據type(internal, netdev, gre)獲取interface 的netdev*/
netdev_open(iface_cfg->name, iface_get_type(iface_cfg, br->cfg), &netdev);
//netdev = rc->class->alloc()實際分配的是netdev_linux, gre是netdev_vport
//rc->class->construct(netdev);對於netdev這種設備要存在, internal和gre是後面創建的
/*設置interface options 只有gre設備纔有*/
error = iface_set_netdev_config(iface_cfg, netdev);
ofproto_port_add(br->ofproto, netdev, ofp_portp);
/*獲取ofport, 並且將ofport與dp_port做映射 ofport_install-->port_construct分配ofport*/
update_port(ofproto, netdev_name);
}
update_port
{
ofport_open(ofproto, &ofproto_port, &pp);
/*
//allocate the ofport
if (ofproto_port->ofp_port == OFPP_NONE) {
if (!strcmp(ofproto->name, ofproto_port->name)) {
ofproto_port->ofp_port = OFPP_LOCAL;
} else {
ofproto_port->ofp_port = alloc_ofp_port(ofproto,
ofproto_port->name);
}
}
*/
ofport_install(ofproto, netdev, &pp);
}
struct ofport {
struct hmap_node hmap_node; /* In struct ofproto's "ports" hmap. */
struct ofproto *ofproto; /* The ofproto that contains this port. */
struct netdev *netdev;
struct ofputil_phy_port pp;
ofp_port_t ofp_port; /* OpenFlow port number. */
};
struct ofport_dpif {
struct hmap_node odp_port_node; /* In dpif_backer's "odp_to_ofport_map". */
struct ofport up;
/*datapath port*/
odp_port_t odp_port;
}
ofport_install(struct ofproto *p, struct netdev *netdev, const struct ofputil_phy_port *pp)
{
/*實際分配ofport_dpif*/
ofport = p->ofproto_class->port_alloc();
ofport->ofproto = p;
ofport->netdev = netdev;
ofport->pp = *pp;
ofport->ofp_port = pp->port_no;
ofport->created = time_msec();
/* Add port to 'p'. */
hmap_insert(&p->ports, &ofport->hmap_node, hash_ofp_port(ofport->ofp_port));
/*map the ofport with dp_port*/
error = p->ofproto_class->port_construct(ofport);
}
ofproto_port_add—>ofproto->ofproto_class->port_add
port_add
{
/*netdev和internal都是獲取的設備名, gre是獲取的gre_system, 所以gre設備只會向add_port一次*/
dp_port_name = netdev_vport_get_dpif_port(netdev, namebuf, sizeof namebuf);
if (!dpif_port_exists(ofproto->backer->dpif, dp_port_name))
{
/*這裏是port_no是openvswitch datapath的port no*/
dpif_port_add(ofproto->backer->dpif, netdev, &port_no)
//dpif->dpif_class->port_add(dpif, netdev, &port_no);
}
}
dpif_linux_port_add(struct dpif *dpif_, struct netdev *netdev,
odp_port_t *port_nop)
{
使用OVS_VPORT_CMD_NEW創建vport於內核中
}
///////////////////////////////////
內核態
int ovs_vport_cmd_new(struct sk_buff *skb, struct genl_info *info)
{
parms.name = nla_data(a[OVS_VPORT_ATTR_NAME]);
parms.type = nla_get_u32(a[OVS_VPORT_ATTR_TYPE]);
parms.options = a[OVS_VPORT_ATTR_OPTIONS];
parms.dp = dp;
parms.port_no = port_no;
parms.upcall_portid = nla_get_u32(a[OVS_VPORT_ATTR_UPCALL_PID]);
vport = new_vport(&parms);--->ovs_vport_add(parms);--->vport_ops->create
}
//normal netdev: eth0 veth0
const struct vport_ops ovs_netdev_vport_ops = {
.type = OVS_VPORT_TYPE_NETDEV,
.create = netdev_create,
.destroy = netdev_destroy,
.get_name = ovs_netdev_get_name,
.send = netdev_send,/*當報文的需要通過該vport發送的處理函數*/
};
struct vport *netdev_create(const struct vport_parms *parms)
{
vport = ovs_vport_alloc(sizeof(struct netdev_vport), &ovs_netdev_vport_ops, parms);
netdev_vport = netdev_vport_priv(vport);
/*find the real dev*/
netdev_vport->dev = dev_get_by_name(ovs_dp_get_net(vport->dp), parms->name);
/*設置ovs內核處理函數, 使netdev收到的報文不再走傳統協議棧*/
netdev_rx_handler_register(netdev_vport->dev, netdev_frame_hook, vport)
}
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;
skb->dev = netdev_vport->dev;
len = skb->len;
/*直接從該dev發送*/
dev_queue_xmit(skb);
}
//internal: bridge port
const struct vport_ops ovs_internal_vport_ops = {
.type = OVS_VPORT_TYPE_INTERNAL,
.create = internal_dev_create,
.destroy = internal_dev_destroy,
.get_name = ovs_netdev_get_name,
.send = internal_dev_recv,
};
truct net_device_ops internal_dev_netdev_ops = {
.ndo_start_xmit = internal_dev_xmit,
};
/*internal net device發送函數就是ovs的處理函數*/
static int internal_dev_xmit(struct sk_buff *skb, struct net_device *netdev)
{
ovs_vport_receive(internal_dev_priv(netdev)->vport, skb, NULL);
}
struct vport *internal_dev_create(const struct vport_parms *parms)
{
vport = ovs_vport_alloc(sizeof(struct netdev_vport), &ovs_internal_vport_ops, parms);
netdev_vport = netdev_vport_priv(vport);
/*創建一個ethernet device, netdev->netdev_ops = &internal_dev_netdev_ops;*/
netdev_vport->dev = alloc_netdev(sizeof(struct internal_dev), parms->name, do_setup)
internal_dev = internal_dev_priv(netdev_vport->dev);
internal_dev->vport = vport;
err = register_netdevice(netdev_vport->dev);
}
/*如果報文指定從internal設備發出, 數據包會重新注入協議棧*/
int internal_dev_recv(struct vport *vport, struct sk_buff *skb)
{
skb->dev = netdev;
skb->pkt_type = PACKET_HOST;
skb->protocol = eth_type_trans(skb, netdev);
skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN);
netif_rx(skb);
}
//gre port
const struct vport_ops ovs_gre_vport_ops = {
.type = OVS_VPORT_TYPE_GRE,
.create = gre_create,
.destroy = gre_tnl_destroy,
.get_name = gre_get_name,
.send = gre_send,
};
整個系統只創建一個gre device在內核
struct vport *gre_create(const struct vport_parms *parms)
{
ovs_net = net_generic(net, ovs_net_id);
if (ovsl_dereference(ovs_net->vport_net.gre_vport)) {
vport = ERR_PTR(-EEXIST);
goto error;
}
vport = ovs_vport_alloc(IFNAMSIZ, &ovs_gre_vport_ops, parms);
}
發送
報文通過gre口發送會根據下發具體action規則添加gre header以及deliver header
int gre_send(struct vport *vport, struct sk_buff *skb)
接收
當系統收到gre報文,去掉了deliver header獲取gre header信息傳遞給gre_rcv,然後進入ovs處理函數進行處理