// Create an internal port in OVS func (self *OvsDriver) CreatePort(intfName, intfType string, vlanTag uint) error { portUuidStr := intfName intfUuidStr := fmt.Sprintf("Intf%s", intfName) portUuid := []libovsdb.UUID{{portUuidStr}} intfUuid := []libovsdb.UUID{{intfUuidStr}} opStr := "insert" var err error = nil // insert/delete a row in Interface table intf := make(map[string]interface{}) intf["name"] = intfName intf["type"] = intfType // Add an entry in Interface table intfOp := libovsdb.Operation{ Op: opStr, Table: "Interface", Row: intf, UUIDName: intfUuidStr, } // insert/delete a row in Port table port := make(map[string]interface{}) port["name"] = intfName if vlanTag != 0 { port["vlan_mode"] = "access" port["tag"] = vlanTag } else { port["vlan_mode"] = "trunk" } port["interfaces"], err = libovsdb.NewOvsSet(intfUuid) if err != nil { return err } // Add an entry in Port table portOp := libovsdb.Operation{ Op: opStr, Table: "Port", Row: port, UUIDName: portUuidStr, } // mutate the Ports column of the row in the Bridge table mutateSet, _ := libovsdb.NewOvsSet(portUuid) mutation := libovsdb.NewMutation("ports", opStr, mutateSet) condition := libovsdb.NewCondition("name", "==", self.OvsBridgeName) mutateOp := libovsdb.Operation{ Op: "mutate", Table: "Bridge", Mutations: []interface{}{mutation}, Where: []interface{}{condition}, } // Perform OVS transaction operations := []libovsdb.Operation{intfOp, portOp, mutateOp} return self.ovsdbTransact(operations) }
// DeletePort deletes a port from OVS func (d *OvsdbDriver) DeletePort(intfName string) error { portUUIDStr := intfName portUUID := []libovsdb.UUID{{portUUIDStr}} opStr := "delete" // insert/delete a row in Interface table condition := libovsdb.NewCondition("name", "==", intfName) intfOp := libovsdb.Operation{ Op: opStr, Table: interfaceTable, Where: []interface{}{condition}, } // insert/delete a row in Port table condition = libovsdb.NewCondition("name", "==", intfName) portOp := libovsdb.Operation{ Op: opStr, Table: portTable, Where: []interface{}{condition}, } // also fetch the port-uuid from cache d.cacheLock.RLock() for uuid, row := range d.cache["Port"] { name := row.Fields["name"].(string) if name == intfName { portUUID = []libovsdb.UUID{uuid} break } } d.cacheLock.RUnlock() // mutate the Ports column of the row in the Bridge table mutateSet, _ := libovsdb.NewOvsSet(portUUID) mutation := libovsdb.NewMutation("ports", opStr, mutateSet) condition = libovsdb.NewCondition("name", "==", d.bridgeName) mutateOp := libovsdb.Operation{ Op: "mutate", Table: bridgeTable, Mutations: []interface{}{mutation}, Where: []interface{}{condition}, } // Perform OVS transaction operations := []libovsdb.Operation{intfOp, portOp, mutateOp} return d.performOvsdbOps(operations) }
// Delete a port from OVS func (self *OvsDriver) DeletePort(intfName string) error { portUuidStr := intfName portUuid := []libovsdb.UUID{{portUuidStr}} opStr := "delete" // insert/delete a row in Interface table condition := libovsdb.NewCondition("name", "==", intfName) intfOp := libovsdb.Operation{ Op: opStr, Table: "Interface", Where: []interface{}{condition}, } // insert/delete a row in Port table condition = libovsdb.NewCondition("name", "==", intfName) portOp := libovsdb.Operation{ Op: opStr, Table: "Port", Where: []interface{}{condition}, } // also fetch the port-uuid from cache for uuid, row := range self.ovsdbCache["Port"] { name := row.Fields["name"].(string) if name == intfName { portUuid = []libovsdb.UUID{{uuid}} break } } // mutate the Ports column of the row in the Bridge table mutateSet, _ := libovsdb.NewOvsSet(portUuid) mutation := libovsdb.NewMutation("ports", opStr, mutateSet) condition = libovsdb.NewCondition("name", "==", self.OvsBridgeName) mutateOp := libovsdb.Operation{ Op: "mutate", Table: "Bridge", Mutations: []interface{}{mutation}, Where: []interface{}{condition}, } // Perform OVS transaction operations := []libovsdb.Operation{intfOp, portOp, mutateOp} return self.ovsdbTransact(operations) }
// **************** OVS driver API ******************** func (self *OvsDriver) CreateBridge(bridgeName string) error { namedUuidStr := "dummy" protocols := []string{"OpenFlow10", "OpenFlow11", "OpenFlow12", "OpenFlow13"} // If the bridge already exists, just return // FIXME: should we delete the old bridge and create new one? if self.IsBridgePresent(bridgeName) { return nil } // simple insert/delete operation brOp := libovsdb.Operation{} bridge := make(map[string]interface{}) bridge["name"] = bridgeName bridge["protocols"], _ = libovsdb.NewOvsSet(protocols) bridge["fail_mode"] = "secure" brOp = libovsdb.Operation{ Op: "insert", Table: "Bridge", Row: bridge, UUIDName: namedUuidStr, } // Inserting/Deleting a Bridge row in Bridge table requires mutating // the open_vswitch table. brUuid := []libovsdb.UUID{{namedUuidStr}} mutateUuid := brUuid mutateSet, _ := libovsdb.NewOvsSet(mutateUuid) mutation := libovsdb.NewMutation("bridges", "insert", mutateSet) condition := libovsdb.NewCondition("_uuid", "==", self.getRootUuid()) // simple mutate operation mutateOp := libovsdb.Operation{ Op: "mutate", Table: "Open_vSwitch", Mutations: []interface{}{mutation}, Where: []interface{}{condition}, } operations := []libovsdb.Operation{brOp, mutateOp} // operations := []libovsdb.Operation{brOp} return self.ovsdbTransact(operations) }
// Delete a bridge from ovs func (self *OvsDriver) DeleteBridge(bridgeName string) error { namedUuidStr := "dummy" brUuid := []libovsdb.UUID{{namedUuidStr}} // simple insert/delete operation brOp := libovsdb.Operation{} condition := libovsdb.NewCondition("name", "==", bridgeName) brOp = libovsdb.Operation{ Op: "delete", Table: "Bridge", Where: []interface{}{condition}, } // also fetch the br-uuid from cache for uuid, row := range self.ovsdbCache["Bridge"] { name := row.Fields["name"].(string) if name == bridgeName { brUuid = []libovsdb.UUID{{uuid}} break } } // Inserting/Deleting a Bridge row in Bridge table requires mutating // the open_vswitch table. mutateUuid := brUuid mutateSet, _ := libovsdb.NewOvsSet(mutateUuid) mutation := libovsdb.NewMutation("bridges", "delete", mutateSet) condition = libovsdb.NewCondition("_uuid", "==", self.getRootUuid()) // simple mutate operation mutateOp := libovsdb.Operation{ Op: "mutate", Table: "Open_vSwitch", Mutations: []interface{}{mutation}, Where: []interface{}{condition}, } operations := []libovsdb.Operation{brOp, mutateOp} return self.ovsdbTransact(operations) }
// AddController : Add controller configuration to OVS func (d *OvsdbDriver) AddController(ipAddr string, portNo uint16) error { // Format target string target := fmt.Sprintf("tcp:%s:%d", ipAddr, portNo) ctrlerUUIDStr := fmt.Sprintf("local") ctrlerUUID := []libovsdb.UUID{libovsdb.UUID{GoUuid: ctrlerUUIDStr}} // If controller already exists, nothing to do if d.IsControllerPresent(target) { return nil } // insert a row in Controller table controller := make(map[string]interface{}) controller["target"] = target // Add an entry in Controller table ctrlerOp := libovsdb.Operation{ Op: "insert", Table: "Controller", Row: controller, UUIDName: ctrlerUUIDStr, } // mutate the Controller column of the row in the Bridge table mutateSet, _ := libovsdb.NewOvsSet(ctrlerUUID) mutation := libovsdb.NewMutation("controller", "insert", mutateSet) condition := libovsdb.NewCondition("name", "==", d.bridgeName) mutateOp := libovsdb.Operation{ Op: "mutate", Table: "Bridge", Mutations: []interface{}{mutation}, Where: []interface{}{condition}, } // Perform OVS transaction operations := []libovsdb.Operation{ctrlerOp, mutateOp} return d.performOvsdbOps(operations) }
// CreateVtep creates a VTEP port on the OVS func (d *OvsdbDriver) CreateVtep(intfName string, vtepRemoteIP string) error { portUUIDStr := intfName intfUUIDStr := fmt.Sprintf("Intf%s", intfName) portUUID := []libovsdb.UUID{{portUUIDStr}} intfUUID := []libovsdb.UUID{{intfUUIDStr}} opStr := "insert" intfType := "vxlan" var err error // insert/delete a row in Interface table intf := make(map[string]interface{}) intf["name"] = intfName intf["type"] = intfType // Special handling for VTEP ports intfOptions := make(map[string]interface{}) intfOptions["remote_ip"] = vtepRemoteIP intfOptions["key"] = "flow" // Insert VNI per flow intf["options"], err = libovsdb.NewOvsMap(intfOptions) if err != nil { log.Errorf("error '%s' creating options from %v \n", err, intfOptions) return err } // Add an entry in Interface table intfOp := libovsdb.Operation{ Op: opStr, Table: interfaceTable, Row: intf, UUIDName: intfUUIDStr, } // insert/delete a row in Port table port := make(map[string]interface{}) port["name"] = intfName port["vlan_mode"] = "trunk" port["interfaces"], err = libovsdb.NewOvsSet(intfUUID) if err != nil { return err } // Add an entry in Port table portOp := libovsdb.Operation{ Op: opStr, Table: portTable, Row: port, UUIDName: portUUIDStr, } // mutate the Ports column of the row in the Bridge table mutateSet, _ := libovsdb.NewOvsSet(portUUID) mutation := libovsdb.NewMutation("ports", opStr, mutateSet) condition := libovsdb.NewCondition("name", "==", d.bridgeName) mutateOp := libovsdb.Operation{ Op: "mutate", Table: bridgeTable, Mutations: []interface{}{mutation}, Where: []interface{}{condition}, } // Perform OVS transaction operations := []libovsdb.Operation{intfOp, portOp, mutateOp} return d.performOvsdbOps(operations) }
// CreatePort creates an OVS port func (d *OvsdbDriver) CreatePort(intfName, intfType, id string, tag int) error { // intfName is assumed to be unique enough to become uuid portUUIDStr := intfName intfUUIDStr := fmt.Sprintf("Intf%s", intfName) portUUID := []libovsdb.UUID{libovsdb.UUID{GoUuid: portUUIDStr}} intfUUID := []libovsdb.UUID{libovsdb.UUID{GoUuid: intfUUIDStr}} opStr := "insert" var err error // insert/delete a row in Interface table idMap := make(map[string]string) intfOp := libovsdb.Operation{} intf := make(map[string]interface{}) intf["name"] = intfName intf["type"] = intfType idMap["endpoint-id"] = id intf["external_ids"], err = libovsdb.NewOvsMap(idMap) if err != nil { return err } // interface table ops intfOp = libovsdb.Operation{ Op: opStr, Table: interfaceTable, Row: intf, UUIDName: intfUUIDStr, } // insert/delete a row in Port table portOp := libovsdb.Operation{} port := make(map[string]interface{}) port["name"] = intfName if tag != 0 { port["vlan_mode"] = "access" port["tag"] = tag } else { port["vlan_mode"] = "trunk" } port["interfaces"], err = libovsdb.NewOvsSet(intfUUID) if err != nil { return err } port["external_ids"], err = libovsdb.NewOvsMap(idMap) if err != nil { return err } portOp = libovsdb.Operation{ Op: opStr, Table: portTable, Row: port, UUIDName: portUUIDStr, } // mutate the Ports column of the row in the Bridge table mutateSet, _ := libovsdb.NewOvsSet(portUUID) mutation := libovsdb.NewMutation("ports", opStr, mutateSet) condition := libovsdb.NewCondition("name", "==", d.bridgeName) mutateOp := libovsdb.Operation{ Op: "mutate", Table: bridgeTable, Mutations: []interface{}{mutation}, Where: []interface{}{condition}, } operations := []libovsdb.Operation{intfOp, portOp, mutateOp} return d.performOvsdbOps(operations) }
// Create or delete an OVS bridge instance func (d *OvsdbDriver) createDeleteBridge(bridgeName, failMode string, op oper) error { namedUUIDStr := "netplugin" brUUID := []libovsdb.UUID{libovsdb.UUID{GoUuid: namedUUIDStr}} protocols := []string{"OpenFlow10", "OpenFlow11", "OpenFlow12", "OpenFlow13"} opStr := "insert" if op != operCreateBridge { opStr = "delete" } // simple insert/delete operation brOp := libovsdb.Operation{} if op == operCreateBridge { bridge := make(map[string]interface{}) bridge["name"] = bridgeName // Enable Openflow1.3 bridge["protocols"], _ = libovsdb.NewOvsSet(protocols) // set fail-mode if required if failMode != "" { bridge["fail_mode"] = "secure" } brOp = libovsdb.Operation{ Op: opStr, Table: bridgeTable, Row: bridge, UUIDName: namedUUIDStr, } } else { condition := libovsdb.NewCondition("name", "==", bridgeName) brOp = libovsdb.Operation{ Op: opStr, Table: bridgeTable, Where: []interface{}{condition}, } // also fetch the br-uuid from cache for uuid, row := range d.cache[bridgeTable] { name := row.Fields["name"].(string) if name == bridgeName { brUUID = []libovsdb.UUID{uuid} break } } } // Inserting/Deleting a Bridge row in Bridge table requires mutating // the open_vswitch table. mutateUUID := brUUID mutateSet, _ := libovsdb.NewOvsSet(mutateUUID) mutation := libovsdb.NewMutation("bridges", opStr, mutateSet) condition := libovsdb.NewCondition("_uuid", "==", d.getRootUUID()) // simple mutate operation mutateOp := libovsdb.Operation{ Op: "mutate", Table: rootTable, Mutations: []interface{}{mutation}, Where: []interface{}{condition}, } operations := []libovsdb.Operation{brOp, mutateOp} return d.performOvsdbOps(operations) }