From 5bd6123d4a9e7bd68f9d90ce8f296e37b50c313d Mon Sep 17 00:00:00 2001 From: Zhang Wei Date: Thu, 6 Apr 2017 18:54:17 +0800 Subject: [PATCH] Add ovs vlan support Support query vlan tag and then apply it to our tap device, through this we can support openvswitch vlan. Signed-off-by: Zhang Wei --- api/descriptions.pb.go | 1 + api/descriptions.proto | 3 +- hypervisor/network/network_linux.go | 36 ++++++++---------------- supervisor/hyperpod.go | 43 +++++++++++++++++------------ 4 files changed, 41 insertions(+), 42 deletions(-) diff --git a/api/descriptions.pb.go b/api/descriptions.pb.go index ff74a76e..8c7d5f18 100644 --- a/api/descriptions.pb.go +++ b/api/descriptions.pb.go @@ -165,6 +165,7 @@ type InterfaceDescription struct { Mac string `protobuf:"bytes,5,opt,name=mac" json:"mac,omitempty"` Gw string `protobuf:"bytes,6,opt,name=gw" json:"gw,omitempty"` TapName string `protobuf:"bytes,7,opt,name=tapName" json:"tapName,omitempty"` + Options string `protobuf:"bytes,8,opt,name=options" json:"options,omitempty"` } func (m *InterfaceDescription) Reset() { *m = InterfaceDescription{} } diff --git a/api/descriptions.proto b/api/descriptions.proto index 799d99ba..504d8517 100644 --- a/api/descriptions.proto +++ b/api/descriptions.proto @@ -57,6 +57,7 @@ message InterfaceDescription { string mac = 5; string gw = 6; string tapName = 7; + string options = 8; } message PortDescription { @@ -110,4 +111,4 @@ message Process { repeated string Args = 7; repeated string Envs = 8; string Workdir = 9; -} \ No newline at end of file +} diff --git a/hypervisor/network/network_linux.go b/hypervisor/network/network_linux.go index 6ad172ce..27e5bbd5 100644 --- a/hypervisor/network/network_linux.go +++ b/hypervisor/network/network_linux.go @@ -793,7 +793,7 @@ func DeleteBridge(name string) error { // AddToBridge attch interface to the bridge, // we only support ovs bridge and linux bridge at present. -func AddToBridge(iface, master *net.Interface) error { +func AddToBridge(iface, master *net.Interface, options string) error { link, err := netlink.LinkByName(master.Name) if err != nil { return err @@ -801,7 +801,7 @@ func AddToBridge(iface, master *net.Interface) error { switch link.Type() { case "openvswitch": - return AddToOpenvswitchBridge(iface, master) + return AddToOpenvswitchBridge(iface, master, options) case "bridge": return AddToLinuxBridge(iface, master) default: @@ -809,29 +809,17 @@ func AddToBridge(iface, master *net.Interface) error { } } -func AddToOpenvswitchBridge(iface, master *net.Interface) error { - glog.V(1).Infof("Found ovs bridge %s, attaching tap %s to it\n", master.Name, iface.Name) - - // Check whether there is already a device with the same name has already been attached - // to the ovs bridge or not. If so, skip the follow attaching operation. - out, err := exec.Command("ovs-vsctl", "list-ports", master.Name).CombinedOutput() - if err != nil { - return err - } - ports := strings.Split(strings.TrimSpace(string(out)), "\n") - for _, port := range ports { - if port == iface.Name { - glog.V(1).Infof("A port named %s already exists on bridge %s, using it.\n", iface.Name, master.Name) - return nil - } - } +func AddToOpenvswitchBridge(iface, master *net.Interface, options string) error { + glog.V(3).Infof("Found ovs bridge %s, attaching tap %s to it\n", master.Name, iface.Name) // ovs command "ovs-vsctl add-port BRIDGE PORT" add netwok device PORT to BRIDGE, // PORT and BRIDGE here indicate the device name respectively. - out, err = exec.Command("ovs-vsctl", "add-port", master.Name, iface.Name).CombinedOutput() + out, err := exec.Command("ovs-vsctl", "--may-exist", "add-port", master.Name, iface.Name).CombinedOutput() if err != nil { return fmt.Errorf("Ovs failed to add port: %s, error :%v", strings.TrimSpace(string(out)), err) } + + out, err = exec.Command("ovs-vsctl", "set", "port", iface.Name, options).CombinedOutput() return nil } @@ -982,7 +970,7 @@ func UpAndAddToBridge(name string) error { glog.Error("cannot find bridge interface ", BridgeIface) return err } - err = AddToBridge(inf, brg) + err = AddToBridge(inf, brg, "") if err != nil { glog.Errorf("cannot add %s to %s ", name, BridgeIface) return err @@ -996,7 +984,7 @@ func UpAndAddToBridge(name string) error { return nil } -func GetTapFd(tapname, bridge string) (device string, tapFile *os.File, err error) { +func GetTapFd(tapname, bridge, options string) (device string, tapFile *os.File, err error) { var ( req ifReq errno syscall.Errno @@ -1036,7 +1024,7 @@ func GetTapFd(tapname, bridge string) (device string, tapFile *os.File, err erro return "", nil, err } - err = AddToBridge(tapIface, bIface) + err = AddToBridge(tapIface, bIface, options) if err != nil { glog.Errorf("Add to bridge failed %s %s", bridge, device) tapFile.Close() @@ -1095,7 +1083,7 @@ func Allocate(vmId, requestedIP string, addrOnly bool) (*Settings, error) { // return nil, err //} - device, tapFile, err := GetTapFd("", BridgeIface) + device, tapFile, err := GetTapFd("", BridgeIface, "") if err != nil { IpAllocator.ReleaseIP(BridgeIPv4Net, net.ParseIP(setting.IPAddress)) return nil, err @@ -1146,7 +1134,7 @@ func Configure(vmId, requestedIP string, addrOnly bool, inf *api.InterfaceDescri }, nil } - device, tapFile, err := GetTapFd(inf.TapName, inf.Bridge) + device, tapFile, err := GetTapFd(inf.TapName, inf.Bridge, inf.Options) if err != nil { return nil, err } diff --git a/supervisor/hyperpod.go b/supervisor/hyperpod.go index 23789af1..b8e33fb6 100644 --- a/supervisor/hyperpod.go +++ b/supervisor/hyperpod.go @@ -67,13 +67,14 @@ type nsListener struct { cmd *exec.Cmd } -func GetBridgeFromIndex(idx int) (string, error) { +func GetBridgeFromIndex(idx int) (string, string, error) { var attr, bridge *netlink.LinkAttrs + var options string links, err := netlink.LinkList() if err != nil { glog.Error(err) - return "", err + return "", "", err } for _, link := range links { @@ -88,7 +89,7 @@ func GetBridgeFromIndex(idx int) (string, error) { } if attr == nil { - return "", fmt.Errorf("cann't find nic whose ifindex is %d", idx) + return "", "", fmt.Errorf("cann't find nic whose ifindex is %d", idx) } for _, link := range links { @@ -103,25 +104,31 @@ func GetBridgeFromIndex(idx int) (string, error) { } if bridge == nil { - return "", fmt.Errorf("cann't find bridge contains nic whose ifindex is %d", idx) + return "", "", fmt.Errorf("cann't find bridge contains nic whose ifindex is %d", idx) } if bridge.Name == "ovs-system" { veth, err := netlink.LinkByIndex(idx) if err != nil { - return "", err + return "", "", err } out, err := exec.Command("ovs-vsctl", "port-to-br", veth.Attrs().Name).CombinedOutput() if err != nil { - return "", err + return "", "", err } bridge.Name = strings.TrimSpace(string(out)) + + out, err = exec.Command("ovs-vsctl", "get", "port", veth.Attrs().Name, "tag").CombinedOutput() + if err != nil { + return "", "", err + } + options = "tag=" + strings.TrimSpace(string(out)) } glog.V(3).Infof("find bridge %s", bridge.Name) - return bridge.Name, nil + return bridge.Name, options, nil } func (hp *HyperPod) initPodNetwork(c *Container) error { @@ -168,7 +175,7 @@ func (hp *HyperPod) initPodNetwork(c *Container) error { glog.V(3).Infof("interface configuration of pod ns is %#v", infos) for _, info := range infos { - bridge, err := GetBridgeFromIndex(info.PeerIndex) + bridge, options, err := GetBridgeFromIndex(info.PeerIndex) if err != nil { glog.Error(err) continue @@ -177,10 +184,11 @@ func (hp *HyperPod) initPodNetwork(c *Container) error { nicId := strconv.Itoa(info.Index) conf := &api.InterfaceDescription{ - Id: nicId, //ip as an id - Lo: false, - Bridge: bridge, - Ip: info.Ip, + Id: nicId, //ip as an id + Lo: false, + Bridge: bridge, + Ip: info.Ip, + Options: options, } if gw_route != nil && gw_route.LinkIndex == info.Index { @@ -263,17 +271,18 @@ func (hp *HyperPod) nsListenerStrap() { continue } - bridge, err := GetBridgeFromIndex(link.Attrs().ParentIndex) + bridge, options, err := GetBridgeFromIndex(link.Attrs().ParentIndex) if err != nil { glog.Error(err) continue } inf := &api.InterfaceDescription{ - Id: strconv.Itoa(link.Attrs().Index), - Lo: false, - Bridge: bridge, - Ip: update.Addr.LinkAddress.String(), + Id: strconv.Itoa(link.Attrs().Index), + Lo: false, + Bridge: bridge, + Ip: update.Addr.LinkAddress.String(), + Options: options, } err = hp.vm.AddNic(inf)