VOL-1558 Update vendored voltha-go and other items
Result of running dep ensure. golang openolt now
builds.
Also update dockerfile to used specific alpine version
Change-Id: I1e5407e25bb0636a241a0650d1e44e5df567f44b
diff --git a/vendor/github.com/opencord/voltha-go/rw_core/utils/flow_utils.go b/vendor/github.com/opencord/voltha-go/rw_core/utils/flow_utils.go
new file mode 100644
index 0000000..10be81a
--- /dev/null
+++ b/vendor/github.com/opencord/voltha-go/rw_core/utils/flow_utils.go
@@ -0,0 +1,377 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package utils
+
+import (
+ "bytes"
+ "github.com/cevaris/ordered_map"
+ "github.com/gogo/protobuf/proto"
+ ofp "github.com/opencord/voltha-protos/go/openflow_13"
+ "strings"
+)
+
+type OfpFlowModArgs map[string]uint64
+
+type FlowArgs struct {
+ MatchFields []*ofp.OfpOxmOfbField
+ Actions []*ofp.OfpAction
+ Command *ofp.OfpFlowModCommand
+ Priority uint32
+ KV OfpFlowModArgs
+}
+
+type GroupArgs struct {
+ GroupId uint32
+ Buckets []*ofp.OfpBucket
+ Command *ofp.OfpGroupModCommand
+}
+
+type FlowsAndGroups struct {
+ Flows *ordered_map.OrderedMap
+ Groups *ordered_map.OrderedMap
+}
+
+func NewFlowsAndGroups() *FlowsAndGroups {
+ var fg FlowsAndGroups
+ fg.Flows = ordered_map.NewOrderedMap()
+ fg.Groups = ordered_map.NewOrderedMap()
+ return &fg
+}
+
+func (fg *FlowsAndGroups) Copy() *FlowsAndGroups {
+ copyFG := NewFlowsAndGroups()
+ iter := fg.Flows.IterFunc()
+ for kv, ok := iter(); ok; kv, ok = iter() {
+ if protoMsg, isMsg := kv.Value.(*ofp.OfpFlowStats); isMsg {
+ copyFG.Flows.Set(kv.Key, proto.Clone(protoMsg))
+ }
+ }
+ iter = fg.Groups.IterFunc()
+ for kv, ok := iter(); ok; kv, ok = iter() {
+ if protoMsg, isMsg := kv.Value.(*ofp.OfpGroupEntry); isMsg {
+ copyFG.Groups.Set(kv.Key, proto.Clone(protoMsg))
+ }
+ }
+ return copyFG
+}
+
+func (fg *FlowsAndGroups) GetFlow(index int) *ofp.OfpFlowStats {
+ iter := fg.Flows.IterFunc()
+ pos := 0
+ for kv, ok := iter(); ok; kv, ok = iter() {
+ if pos == index {
+ if protoMsg, isMsg := kv.Value.(*ofp.OfpFlowStats); isMsg {
+ return protoMsg
+ }
+ return nil
+ }
+ pos += 1
+ }
+ return nil
+}
+
+func (fg *FlowsAndGroups) ListFlows() []*ofp.OfpFlowStats {
+ flows := make([]*ofp.OfpFlowStats, 0)
+ iter := fg.Flows.IterFunc()
+ for kv, ok := iter(); ok; kv, ok = iter() {
+ if protoMsg, isMsg := kv.Value.(*ofp.OfpFlowStats); isMsg {
+ flows = append(flows, protoMsg)
+ }
+ }
+ return flows
+}
+
+func (fg *FlowsAndGroups) ListGroups() []*ofp.OfpGroupEntry {
+ groups := make([]*ofp.OfpGroupEntry, 0)
+ iter := fg.Groups.IterFunc()
+ for kv, ok := iter(); ok; kv, ok = iter() {
+ if protoMsg, isMsg := kv.Value.(*ofp.OfpGroupEntry); isMsg {
+ groups = append(groups, protoMsg)
+ }
+ }
+ return groups
+}
+
+func (fg *FlowsAndGroups) String() string {
+ var buffer bytes.Buffer
+ iter := fg.Flows.IterFunc()
+ for kv, ok := iter(); ok; kv, ok = iter() {
+ if protoMsg, isMsg := kv.Value.(*ofp.OfpFlowStats); isMsg {
+ buffer.WriteString("\nFlow:\n")
+ buffer.WriteString(proto.MarshalTextString(protoMsg))
+ buffer.WriteString("\n")
+ }
+ }
+ iter = fg.Groups.IterFunc()
+ for kv, ok := iter(); ok; kv, ok = iter() {
+ if protoMsg, isMsg := kv.Value.(*ofp.OfpGroupEntry); isMsg {
+ buffer.WriteString("\nGroup:\n")
+ buffer.WriteString(proto.MarshalTextString(protoMsg))
+ buffer.WriteString("\n")
+ }
+ }
+ return buffer.String()
+}
+
+func (fg *FlowsAndGroups) AddFlow(flow *ofp.OfpFlowStats) {
+ if fg.Flows == nil {
+ fg.Flows = ordered_map.NewOrderedMap()
+ }
+ if fg.Groups == nil {
+ fg.Groups = ordered_map.NewOrderedMap()
+ }
+ //Add flow only if absent
+ if _, exist := fg.Flows.Get(flow.Id); !exist {
+ fg.Flows.Set(flow.Id, flow)
+ }
+}
+
+//AddFrom add flows and groups from the argument into this structure only if they do not already exist
+func (fg *FlowsAndGroups) AddFrom(from *FlowsAndGroups) {
+ iter := from.Flows.IterFunc()
+ for kv, ok := iter(); ok; kv, ok = iter() {
+ if protoMsg, isMsg := kv.Value.(*ofp.OfpFlowStats); isMsg {
+ if _, exist := fg.Flows.Get(protoMsg.Id); !exist {
+ fg.Flows.Set(protoMsg.Id, protoMsg)
+ }
+ }
+ }
+ iter = from.Groups.IterFunc()
+ for kv, ok := iter(); ok; kv, ok = iter() {
+ if protoMsg, isMsg := kv.Value.(*ofp.OfpGroupEntry); isMsg {
+ if _, exist := fg.Groups.Get(protoMsg.Stats.GroupId); !exist {
+ fg.Groups.Set(protoMsg.Stats.GroupId, protoMsg)
+ }
+ }
+ }
+}
+
+type DeviceRules struct {
+ Rules map[string]*FlowsAndGroups
+}
+
+func NewDeviceRules() *DeviceRules {
+ var dr DeviceRules
+ dr.Rules = make(map[string]*FlowsAndGroups)
+ return &dr
+}
+
+func (dr *DeviceRules) Copy() *DeviceRules {
+ copyDR := NewDeviceRules()
+ for key, val := range dr.Rules {
+ copyDR.Rules[key] = val.Copy()
+ }
+ return copyDR
+}
+
+func (dr *DeviceRules) ClearFlows(deviceId string) {
+ if _, exist := dr.Rules[deviceId]; exist {
+ dr.Rules[deviceId].Flows = ordered_map.NewOrderedMap()
+ }
+}
+
+func (dr *DeviceRules) AddFlow(deviceId string, flow *ofp.OfpFlowStats) {
+ if _, exist := dr.Rules[deviceId]; !exist {
+ dr.Rules[deviceId] = NewFlowsAndGroups()
+ }
+ dr.Rules[deviceId].AddFlow(flow)
+}
+
+func (dr *DeviceRules) GetRules() map[string]*FlowsAndGroups {
+ return dr.Rules
+}
+
+func (dr *DeviceRules) String() string {
+ var buffer bytes.Buffer
+ for key, value := range dr.Rules {
+ buffer.WriteString("DeviceId:")
+ buffer.WriteString(key)
+ buffer.WriteString(value.String())
+ buffer.WriteString("\n\n")
+ }
+ return buffer.String()
+}
+
+func (dr *DeviceRules) AddFlowsAndGroup(deviceId string, fg *FlowsAndGroups) {
+ if _, ok := dr.Rules[deviceId]; !ok {
+ dr.Rules[deviceId] = NewFlowsAndGroups()
+ }
+ dr.Rules[deviceId] = fg
+}
+
+// CreateEntryIfNotExist creates a new deviceId in the Map if it does not exist and assigns an
+// empty FlowsAndGroups to it. Otherwise, it does nothing.
+func (dr *DeviceRules) CreateEntryIfNotExist(deviceId string) {
+ if _, ok := dr.Rules[deviceId]; !ok {
+ dr.Rules[deviceId] = NewFlowsAndGroups()
+ }
+}
+
+/*
+ * Common flow routines
+ */
+
+//FindOverlappingFlows return a list of overlapping flow(s) where mod is the flow request
+func FindOverlappingFlows(flows []*ofp.OfpFlowStats, mod *ofp.OfpFlowMod) []*ofp.OfpFlowStats {
+ return nil //TODO - complete implementation
+}
+
+// FindFlowById returns the index of the flow in the flows array if present. Otherwise, it returns -1
+func FindFlowById(flows []*ofp.OfpFlowStats, flow *ofp.OfpFlowStats) int {
+ for idx, f := range flows {
+ if flow.Id == f.Id {
+ return idx
+ }
+ }
+ return -1
+}
+
+// FindFlows returns the index in flows where flow if present. Otherwise, it returns -1
+func FindFlows(flows []*ofp.OfpFlowStats, flow *ofp.OfpFlowStats) int {
+ for idx, f := range flows {
+ if FlowMatch(f, flow) {
+ return idx
+ }
+ }
+ return -1
+}
+
+//FlowMatch returns true if two flows matches on the following flow attributes:
+//TableId, Priority, Flags, Cookie, Match
+func FlowMatch(f1 *ofp.OfpFlowStats, f2 *ofp.OfpFlowStats) bool {
+ keysMatter := []string{"TableId", "Priority", "Flags", "Cookie", "Match"}
+ for _, key := range keysMatter {
+ switch key {
+ case "TableId":
+ if f1.TableId != f2.TableId {
+ return false
+ }
+ case "Priority":
+ if f1.Priority != f2.Priority {
+ return false
+ }
+ case "Flags":
+ if f1.Flags != f2.Flags {
+ return false
+ }
+ case "Cookie":
+ if f1.Cookie != f2.Cookie {
+ return false
+ }
+ case "Match":
+ if strings.Compare(f1.Match.String(), f2.Match.String()) != 0 {
+ return false
+ }
+ }
+ }
+ return true
+}
+
+//FlowMatchesMod returns True if given flow is "covered" by the wildcard flow_mod, taking into consideration of
+//both exact matches as well as masks-based match fields if any. Otherwise return False
+func FlowMatchesMod(flow *ofp.OfpFlowStats, mod *ofp.OfpFlowMod) bool {
+ //Check if flow.cookie is covered by mod.cookie and mod.cookie_mask
+ if (flow.Cookie & mod.CookieMask) != (mod.Cookie & mod.CookieMask) {
+ return false
+ }
+
+ //Check if flow.table_id is covered by flow_mod.table_id
+ if mod.TableId != uint32(ofp.OfpTable_OFPTT_ALL) && flow.TableId != mod.TableId {
+ return false
+ }
+
+ //Check out_port
+ if (mod.OutPort&0x7fffffff) != uint32(ofp.OfpPortNo_OFPP_ANY) && !FlowHasOutPort(flow, mod.OutPort) {
+ return false
+ }
+
+ // Check out_group
+ if (mod.OutGroup&0x7fffffff) != uint32(ofp.OfpGroup_OFPG_ANY) && !FlowHasOutGroup(flow, mod.OutGroup) {
+ return false
+ }
+
+ //Priority is ignored
+
+ //Check match condition
+ //If the flow_mod match field is empty, that is a special case and indicates the flow entry matches
+ if (mod.Match == nil) || (mod.Match.OxmFields == nil) {
+ //If we got this far and the match is empty in the flow spec, than the flow matches
+ return true
+ } // TODO : implement the flow match analysis
+ return false
+
+}
+
+//FlowHasOutPort returns True if flow has a output command with the given out_port
+func FlowHasOutPort(flow *ofp.OfpFlowStats, outPort uint32) bool {
+ for _, instruction := range flow.Instructions {
+ if instruction.Type == uint32(ofp.OfpInstructionType_OFPIT_APPLY_ACTIONS) {
+ if instruction.GetActions() == nil {
+ return false
+ }
+ for _, action := range instruction.GetActions().Actions {
+ if action.Type == ofp.OfpActionType_OFPAT_OUTPUT {
+ if (action.GetOutput() != nil) && (action.GetOutput().Port == outPort) {
+ return true
+ }
+ }
+
+ }
+ }
+ }
+ return false
+}
+
+//FlowHasOutGroup return True if flow has a output command with the given out_group
+func FlowHasOutGroup(flow *ofp.OfpFlowStats, groupID uint32) bool {
+ for _, instruction := range flow.Instructions {
+ if instruction.Type == uint32(ofp.OfpInstructionType_OFPIT_APPLY_ACTIONS) {
+ if instruction.GetActions() == nil {
+ return false
+ }
+ for _, action := range instruction.GetActions().Actions {
+ if action.Type == ofp.OfpActionType_OFPAT_GROUP {
+ if (action.GetGroup() != nil) && (action.GetGroup().GroupId == groupID) {
+ return true
+ }
+ }
+
+ }
+ }
+ }
+ return false
+}
+
+//FindGroup returns index of group if found, else returns -1
+func FindGroup(groups []*ofp.OfpGroupEntry, groupId uint32) int {
+ for idx, group := range groups {
+ if group.Desc.GroupId == groupId {
+ return idx
+ }
+ }
+ return -1
+}
+
+func FlowsDeleteByGroupId(flows []*ofp.OfpFlowStats, groupId uint32) (bool, []*ofp.OfpFlowStats) {
+ toKeep := make([]*ofp.OfpFlowStats, 0)
+
+ for _, f := range flows {
+ if !FlowHasOutGroup(f, groupId) {
+ toKeep = append(toKeep, f)
+ }
+ }
+ return len(toKeep) < len(flows), toKeep
+}