Example #1
1
func newFlowEntry(req ofp4.FlowMod) (*flowEntry, error) {
	reqMatch := match{}
	if err := reqMatch.UnmarshalBinary(req.Match().OxmFields()); err != nil {
		return nil, err
	}
	entry := &flowEntry{
		lock:        &sync.RWMutex{},
		fields:      reqMatch,
		cookie:      req.Cookie(),
		created:     time.Now(),
		idleTimeout: req.IdleTimeout(),
		hardTimeout: req.HardTimeout(),
		instWrite:   makeActionSet(),
		instExp:     make(map[int][]instExperimenter),
	}
	if err := entry.importInstructions(req.Instructions()); err != nil {
		return nil, err
	}
	return entry, nil
}
Example #2
0
func (pipe Pipeline) addFlowEntry(req ofp4.FlowMod) error {
	tableId := req.TableId()
	if tableId > ofp4.OFPTT_MAX {
		return ofp4.MakeErrorMsg(
			ofp4.OFPET_FLOW_MOD_FAILED,
			ofp4.OFPFMFC_BAD_TABLE_ID,
		)
	}
	pipe.lock.Lock()
	defer pipe.lock.Unlock()

	var table *flowTable
	if trial, ok := pipe.flows[tableId]; ok {
		table = trial
	} else {
		table = &flowTable{
			lock:    &sync.RWMutex{},
			feature: makeFlowTableFeature(),
		}
		pipe.flows[tableId] = table
	}
	return table.addFlowEntry(req, pipe)
}
Example #3
0
func (self *flowTable) addFlowEntry(req ofp4.FlowMod, pipe Pipeline) error {
	flow, e1 := newFlowEntry(req)
	if e1 != nil {
		return e1
	}
	if err := self.feature.accepts(flow, req.Priority()); err != nil {
		return err
	}

	self.lock.Lock()
	defer self.lock.Unlock()

	var priority *flowPriority
	i := sort.Search(len(self.priorities), func(k int) bool {
		return self.priorities[k].priority <= req.Priority() // descending order
	})
	if i == len(self.priorities) || self.priorities[i].priority != req.Priority() {
		priority = &flowPriority{
			lock:     &sync.RWMutex{},
			priority: req.Priority(),
			flows:    make(map[uint32][]*flowEntry),
		}
		self.priorities = append(self.priorities, nil)
		copy(self.priorities[i+1:], self.priorities[i:])
		self.priorities[i] = priority
	} else {
		priority = self.priorities[i]
	}

	priority.lock.Lock()
	defer priority.lock.Unlock()

	key := priority.hash.Key(matchHash(flow.fields))

	flows := []*flowEntry{flow} // prepare for rebuild
	for k, fs := range priority.flows {
		if k == key {
			for _, f := range fs {
				if conflict, err := flow.fields.Conflict(f.fields); err != nil {
					return err
				} else if req.Flags()&ofp4.OFPFF_CHECK_OVERLAP != 0 && !conflict {
					return ofp4.MakeErrorMsg(ofp4.OFPET_FLOW_MOD_FAILED, ofp4.OFPFMFC_OVERLAP)
				}

				if isEqual, err := flow.fields.Equal(f.fields); err != nil {
					return err
				} else if isEqual {
					// old entry will be cleared
					if req.Flags()&ofp4.OFPFF_RESET_COUNTS == 0 {
						// counters should be copied
						flow.packetCount = f.packetCount
						flow.byteCount = f.byteCount
					}
				} else {
					flows = append(flows, f)
				}
			}
		} else {
			flows = append(flows, fs...)
		}
	}

	if portNo, act := hookDot11Action(req.Match().OxmFields()); portNo != 0 && len(act) != 0 {
		if port := pipe.getPort(portNo); port != nil {
			if err := port.Vendor(gopenflow.MgmtFrameAdd(act)).(error); err != nil {
				return err
			}
		}
	}
	priority.rebuildIndex(flows)
	self.activeCount = uint32(len(flows))
	return nil
}