func (self match) UnmarshalBinary(msg []byte) error { exps := make(map[uint32]bool) for _, oxm := range ofp4.Oxm(msg).Iter() { hdr := oxm.Header() switch hdr.Class() { case ofp4.OFPXMC_OPENFLOW_BASIC: self[OxmKeyBasic(hdr.Type())] = OxmValueMask{ Value: oxm.Value(), Mask: oxm.Mask(), } case ofp4.OFPXMC_EXPERIMENTER: exps[ofp4.OxmExperimenterHeader(oxm).Experimenter()] = true default: return ofp4.MakeErrorMsg( ofp4.OFPET_BAD_MATCH, ofp4.OFPBMC_BAD_TYPE, ) } } for exp, _ := range exps { if handle, ok := oxmHandlers[exp]; ok { for k, v := range handle.Parse(msg) { oxmKeys[k] = exp self[k] = v } } else { return ofp4.MakeErrorMsg( ofp4.OFPET_BAD_MATCH, ofp4.OFPBRC_BAD_LEN, ) } } return nil }
func (self oxmNxm) Parse(buf []byte) map[OxmKey]OxmPayload { ret := make(map[OxmKey]OxmPayload) for _, oxm := range ofp4.Oxm(buf).Iter() { hdr := oxm.Header() length := hdr.Length() if hdr.HasMask() { length = length / 2 } switch hdr.Class() { case ofp4.OFPXMC_NXM_0, ofp4.OFPXMC_NXM_1: ret[OxmKeyBasic(hdr.Type())] = OxmValueMask{ Value: oxm[4 : 4+length], Mask: oxm[4+length:], } } } return ret }
func (self match) Expand() (match, error) { var exps []uint32 ret := make(map[OxmKey]OxmPayload) for k, v := range self { oxm := ofp4.Oxm(k.Bytes(v)) if oxm.Header().Class() == ofp4.OFPXMC_EXPERIMENTER { exps = append(exps, ofp4.OxmExperimenterHeader(oxm).Experimenter()) } ret[k] = v } oxmBasicHandler.Expand(ret) for _, exp := range exps { if handle, ok := oxmHandlers[exp]; !ok { return nil, ofp4.MakeErrorMsg( ofp4.OFPET_BAD_MATCH, ofp4.OFPBMC_BAD_TYPE, ) } else if err := handle.Expand(ret); err != nil { return nil, err } } return ret, nil }
// See openflow switch 1.3.4 spec "Flow Table Modification Messages" page 40 func (self flowTableFeature) accepts(entry *flowEntry, priority uint16) error { isTableMiss := false if len(entry.fields) == 0 && priority == 0 { isTableMiss = true } var instKeys instructionKeyList if isTableMiss && self.miss.inst != nil { instKeys = instructionKeyList(self.miss.inst) } else if self.hit.inst != nil { instKeys = instructionKeyList(self.hit.inst) } if entry.instGoto != 0 { if instKeys != nil && !instKeys.Have(uint16(ofp4.OFPIT_GOTO_TABLE)) { return ofp4.MakeErrorMsg( ofp4.OFPET_BAD_INSTRUCTION, ofp4.OFPBIC_UNSUP_INST, ) } var next []uint8 if isTableMiss && self.miss.next != nil { next = self.miss.next } else if self.hit.next != nil { next = self.hit.next } if next != nil { supported := false for _, tableId := range next { if entry.instGoto == tableId { supported = true } } if !supported { return ofp4.MakeErrorMsg( ofp4.OFPET_BAD_INSTRUCTION, ofp4.OFPBIC_BAD_TABLE_ID, ) } } } if entry.instMetadata != nil { if instKeys != nil && !instKeys.Have(uint16(ofp4.OFPIT_WRITE_METADATA)) { return ofp4.MakeErrorMsg( ofp4.OFPET_BAD_INSTRUCTION, ofp4.OFPBIC_UNSUP_INST, ) } if entry.instMetadata.metadata&^self.metadataWrite != 0 { return ofp4.MakeErrorMsg( ofp4.OFPET_BAD_INSTRUCTION, ofp4.OFPBIC_UNSUP_METADATA, ) } if entry.instMetadata.mask&^self.metadataWrite != 0 { return ofp4.MakeErrorMsg( ofp4.OFPET_BAD_INSTRUCTION, ofp4.OFPBIC_UNSUP_METADATA_MASK, ) } } if !isTableMiss && self.match != nil { unavailable := func(id oxmId) bool { for _, k := range self.match { if k == id { return false } } return true } for k, p := range entry.fields { for _, oxm := range ofp4.Oxm(k.Bytes(p)).Iter() { var id oxmId hdr := oxm.Header() switch hdr.Type() { case ofp4.OFPXMC_OPENFLOW_BASIC: id = oxmBasicHandler.OxmId(uint32(hdr)) case ofp4.OFPXMC_EXPERIMENTER: exp := ofp4.OxmExperimenterHeader(oxm).Experimenter() id = [...]uint32{ oxmHandlers[exp].OxmId(uint32(hdr)), exp, } default: return ofp4.MakeErrorMsg( ofp4.OFPET_BAD_MATCH, ofp4.OFPBMC_BAD_TYPE, ) } if unavailable(id) { return ofp4.MakeErrorMsg( ofp4.OFPET_BAD_MATCH, ofp4.OFPBMC_BAD_FIELD, ) } } } for _, k := range self.wildcards { if unavailable(k) { return ofp4.MakeErrorMsg( ofp4.OFPET_BAD_MATCH, ofp4.OFPBMC_BAD_WILDCARDS, ) } } } if len([]action(entry.instApply)) > 0 { if instKeys != nil && !instKeys.Have(uint16(ofp4.OFPIT_APPLY_ACTIONS)) { return ofp4.MakeErrorMsg( ofp4.OFPET_BAD_INSTRUCTION, ofp4.OFPBIC_UNSUP_INST, ) } var keys []actionKey if isTableMiss && self.miss.applyActions != nil { keys = self.miss.applyActions } else if self.hit.applyActions != nil { keys = self.hit.applyActions } if keys != nil { for _, act := range []action(entry.instApply) { aKey := act.Key() if !actionKeyList(keys).Have(aKey) { return ofp4.MakeErrorMsg( ofp4.OFPET_BAD_ACTION, ofp4.OFPBAC_BAD_TYPE, ) } } // XXX: Experimenter } } if entry.instWrite.Len() > 0 { if instKeys != nil && !instKeys.Have(uint16(ofp4.OFPIT_WRITE_ACTIONS)) { return ofp4.MakeErrorMsg( ofp4.OFPET_BAD_INSTRUCTION, ofp4.OFPBIC_UNSUP_INST, ) } var keys []actionKey if isTableMiss && self.miss.writeActions != nil { keys = self.miss.writeActions } else if self.hit.writeActions != nil { keys = self.hit.writeActions } if keys != nil { for _, a := range entry.instWrite.hash { if !actionKeyList(keys).Have(a.Key()) { return ofp4.MakeErrorMsg( ofp4.OFPET_BAD_ACTION, ofp4.OFPBAC_BAD_TYPE, ) } } for k, _ := range entry.instWrite.exp { if !actionKeyList(keys).Have(k) { return ofp4.MakeErrorMsg( ofp4.OFPET_BAD_ACTION, ofp4.OFPBAC_BAD_TYPE, ) } } } } for _, insts := range entry.instExp { for _, inst := range insts { if instKeys != nil && !instKeys.Have(inst.Experimenter) { return ofp4.MakeErrorMsg( ofp4.OFPET_BAD_INSTRUCTION, ofp4.OFPBIC_UNSUP_INST, ) } } } if entry.instMeter != 0 { if instKeys != nil && !instKeys.Have(uint16(ofp4.OFPIT_METER)) { return ofp4.MakeErrorMsg( ofp4.OFPET_BAD_INSTRUCTION, ofp4.OFPBIC_UNSUP_INST, ) } } return nil }