From 41e3a0e75b30ea55c2166a653e740cb1991948b2 Mon Sep 17 00:00:00 2001 From: wgrayson Date: Wed, 21 Apr 2021 18:19:48 -0700 Subject: [PATCH 1/2] Add meter mod Signed-off-by: wgrayson --- openflow13/meter.go | 261 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 261 insertions(+) create mode 100644 openflow13/meter.go diff --git a/openflow13/meter.go b/openflow13/meter.go new file mode 100644 index 0000000..15c5ea7 --- /dev/null +++ b/openflow13/meter.go @@ -0,0 +1,261 @@ +package openflow13 + +// This file has all meter related defs + +import ( + "encoding/binary" + + log "github.com/sirupsen/logrus" + + "github.com/contiv/libOpenflow/common" + "github.com/contiv/libOpenflow/util" +) + +const ( + OFPMBT13_DROP = 1 /* Drop packet. */ + OFPMBT13_DSCP_REMARK = 2 /* Remark DSCP in the IP header. */ + OFPMBT13_EXPERIMENTER = 0xFFFF /* Experimenter meter band. */ + + OFPMC_ADD = 0 /* New meter. */ + OFPMC_MODIFY = 1 /* Modify specified meter. */ + OFPMC_DELETE = 2 /* Delete specified meter. */ + + OFPMF13_KBPS = 0b0001 /* Rate value in kb/s (kilo-bit per second). */ + OFPMF13_PKTPS = 0b0010 /* Rate value in packet/sec. */ + OFPMF13_BURST = 0b0100 /* Do burst size. */ + OFPMF13_STATS = 0b1000 /* Collect statistics. */ +) + +type MeterBandHeader struct { + Type uint16 /* One of OFPMBT13_*. */ + Length uint16 /* Length in bytes of this band. */ + Rate uint32 /* Rate for this band. */ + BurstSize uint32 /* Size of bursts. */ +} + +func NewMeterBandHeader() *MeterBandHeader { + return &MeterBandHeader{ + Type: OFPMBT13_DROP, + Length: 16, + Rate: 100, + BurstSize: 200, + } +} + +func (m *MeterBandHeader) Len() (n uint16) { + return 12 +} + +func (m *MeterBandHeader) MarshalBinary() (data []byte, err error) { + data = make([]byte, 12) + n := 0 + binary.BigEndian.PutUint16(data[n:], m.Type) + n += 2 + binary.BigEndian.PutUint16(data[n:], m.Length) + n += 2 + binary.BigEndian.PutUint32(data[n:], m.Rate) + n += 4 + binary.BigEndian.PutUint32(data[n:], m.BurstSize) + + return +} + +func (m *MeterBandHeader) UnmarshalBinary(data []byte) error { + n := 0 + m.Type = binary.BigEndian.Uint16(data[n:]) + n += 2 + m.Length = binary.BigEndian.Uint16(data[n:]) + n += 2 + m.Rate = binary.BigEndian.Uint32(data[n:]) + n += 4 + m.BurstSize = binary.BigEndian.Uint32(data[n:]) + + return nil +} + +type MeterBandDrop struct { + MeterBandHeader /* Type: OFPMBT13_DROP. */ + pad [4]uint8 +} + +func (m *MeterBandDrop) Len() (n uint16) { + return m.MeterBandHeader.Len() + 4 +} + +func (m *MeterBandDrop) MarshalBinary() (data []byte, err error) { + data, err = m.MeterBandHeader.MarshalBinary() + if err != nil { + return nil, err + } + bytes := make([]byte, 4) + return append(data, bytes...), nil +} + +func (m *MeterBandDrop) UnmarshalBinary(data []byte) error { + n := 0 + m.MeterBandHeader.UnmarshalBinary(data[n:]) + n += int(m.MeterBandHeader.Len()) + + return nil +} + +type MeterBandDSCP struct { + MeterBandHeader /* Type: OFPMBT13_DSCP_REMARK. */ + PrecLevel uint8 /* Number of drop precedence level to add. */ + pad [3]uint8 +} + +func (m *MeterBandDSCP) Len() (n uint16) { + return m.MeterBandHeader.Len() + 4 +} + +func (m *MeterBandDSCP) MarshalBinary() (data []byte, err error) { + data, err = m.MeterBandHeader.MarshalBinary() + if err != nil { + return nil, err + } + bytes := make([]byte, 4) + bytes[0] = m.PrecLevel + return append(data, bytes...), nil +} + +func (m *MeterBandDSCP) UnmarshalBinary(data []byte) error { + n := 0 + m.MeterBandHeader.UnmarshalBinary(data[n:]) + n += int(m.MeterBandHeader.Len()) + m.PrecLevel = data[n] + + return nil +} + +type MeterBandExperimenter struct { + MeterBandHeader + Experimenter uint32 /* Experimenter ID which takes the same form as in struct ofp_experimenter_header. */ +} + +func (m *MeterBandExperimenter) Len() (n uint16) { + return m.MeterBandHeader.Len() + 4 +} + +func (m *MeterBandExperimenter) MarshalBinary() (data []byte, err error) { + data, err = m.MeterBandHeader.MarshalBinary() + if err != nil { + return nil, err + } + bytes := make([]byte, 4) + binary.BigEndian.PutUint32(bytes, m.Experimenter) + return append(data, bytes...), nil +} + +func (m *MeterBandExperimenter) UnmarshalBinary(data []byte) error { + n := 0 + m.MeterBandHeader.UnmarshalBinary(data[n:]) + n += int(m.MeterBandHeader.Len()) + m.Experimenter = binary.BigEndian.Uint32(data[n:]) + + return nil +} + +// MeterMod message +type MeterMod struct { + common.Header + Command uint16 /* One of OFPMC_*. */ + Flags uint16 /* Set of OFPMF_*. */ + MeterId uint32 /* Meter instance. */ + MeterBands []util.Message /* List of MeterBand*. */ +} + +// Create a new meter mod message +func NewMeterMod() *MeterMod { + m := new(MeterMod) + m.Header = NewOfp13Header() + m.Header.Type = Type_MeterMod + + m.Command = OFPMC_ADD + m.Flags = OFPMF13_PKTPS + m.MeterId = 1 + m.MeterBands = make([]util.Message, 0) + return m +} + +// Add a meterBand to meter mod +func (m *MeterMod) AddMeterBand(mb util.Message) { + m.MeterBands = append(m.MeterBands, mb) +} + +func (m *MeterMod) Len() (n uint16) { + n = m.Header.Len() + n += 8 + if m.Command == OFPMC_DELETE { + return + } + + for _, b := range m.MeterBands { + n += b.Len() + } + + return +} + +func (m *MeterMod) MarshalBinary() (data []byte, err error) { + m.Header.Length = m.Len() + data, err = m.Header.MarshalBinary() + + bytes := make([]byte, 8) + n := 0 + binary.BigEndian.PutUint16(bytes[n:], m.Command) + n += 2 + binary.BigEndian.PutUint16(bytes[n:], m.Flags) + n += 2 + binary.BigEndian.PutUint32(bytes[n:], m.MeterId) + n += 4 + data = append(data, bytes...) + + for _, mb := range m.MeterBands { + bytes, err = mb.MarshalBinary() + data = append(data, bytes...) + log.Debugf("Metermod band: %v", bytes) + } + + log.Debugf("Metermod(%d): %v", len(data), data) + + return +} + +func (m *MeterMod) UnmarshalBinary(data []byte) error { + n := 0 + m.Header.UnmarshalBinary(data[n:]) + n += int(m.Header.Len()) + + m.Command = binary.BigEndian.Uint16(data[n:]) + n += 2 + m.Flags = binary.BigEndian.Uint16(data[n:]) + n += 2 + m.MeterId = binary.BigEndian.Uint32(data[n:]) + n += 4 + + for n < int(m.Header.Length) { + mbh := new(MeterBandHeader) + mbh.UnmarshalBinary(data[n:]) + n += int(mbh.Len()) + switch mbh.Type { + case OFPMBT13_DROP: + mbDrop := new(MeterBandDrop) + mbDrop.MeterBandHeader = *mbh + m.MeterBands = append(m.MeterBands, mbDrop) + case OFPMBT13_DSCP_REMARK: + mbDscp := new(MeterBandDSCP) + mbDscp.MeterBandHeader = *mbh + mbDscp.PrecLevel = data[n] + m.MeterBands = append(m.MeterBands, mbDscp) + case OFPMBT13_EXPERIMENTER: + mbExp := new(MeterBandExperimenter) + mbExp.MeterBandHeader = *mbh + mbExp.Experimenter = binary.BigEndian.Uint32(data[n:]) + m.MeterBands = append(m.MeterBands, mbExp) + } + n += 4 + } + + return nil +} From 3a787d960766190d8a78fa8c879567117806a1f0 Mon Sep 17 00:00:00 2001 From: wgrayson Date: Tue, 18 May 2021 13:59:42 -0700 Subject: [PATCH 2/2] Polish code 1. Add const to avoid hardcode. 2. Use Len() to avoid append. Signed-off-by: wgrayson --- openflow13/meter.go | 84 ++++++++++++++++++++++++++------------------- 1 file changed, 48 insertions(+), 36 deletions(-) diff --git a/openflow13/meter.go b/openflow13/meter.go index 15c5ea7..9f3898f 100644 --- a/openflow13/meter.go +++ b/openflow13/meter.go @@ -24,6 +24,9 @@ const ( OFPMF13_PKTPS = 0b0010 /* Rate value in packet/sec. */ OFPMF13_BURST = 0b0100 /* Do burst size. */ OFPMF13_STATS = 0b1000 /* Collect statistics. */ + + METER_BAND_HEADER_LEN = 12 + METER_BAND_LEN = 16 ) type MeterBandHeader struct { @@ -35,19 +38,16 @@ type MeterBandHeader struct { func NewMeterBandHeader() *MeterBandHeader { return &MeterBandHeader{ - Type: OFPMBT13_DROP, - Length: 16, - Rate: 100, - BurstSize: 200, + Length: METER_BAND_LEN, } } func (m *MeterBandHeader) Len() (n uint16) { - return 12 + return METER_BAND_HEADER_LEN } func (m *MeterBandHeader) MarshalBinary() (data []byte, err error) { - data = make([]byte, 12) + data = make([]byte, m.Len()) n := 0 binary.BigEndian.PutUint16(data[n:], m.Type) n += 2 @@ -79,16 +79,19 @@ type MeterBandDrop struct { } func (m *MeterBandDrop) Len() (n uint16) { - return m.MeterBandHeader.Len() + 4 + return METER_BAND_LEN } func (m *MeterBandDrop) MarshalBinary() (data []byte, err error) { - data, err = m.MeterBandHeader.MarshalBinary() + data = make([]byte, m.Len()) + n := 0 + mbHdrBytes, err := m.MeterBandHeader.MarshalBinary() if err != nil { return nil, err } - bytes := make([]byte, 4) - return append(data, bytes...), nil + copy(data, mbHdrBytes) + n += METER_BAND_HEADER_LEN + return } func (m *MeterBandDrop) UnmarshalBinary(data []byte) error { @@ -106,17 +109,20 @@ type MeterBandDSCP struct { } func (m *MeterBandDSCP) Len() (n uint16) { - return m.MeterBandHeader.Len() + 4 + return METER_BAND_LEN } func (m *MeterBandDSCP) MarshalBinary() (data []byte, err error) { - data, err = m.MeterBandHeader.MarshalBinary() + data = make([]byte, m.Len()) + n := 0 + mbHdrBytes, err := m.MeterBandHeader.MarshalBinary() if err != nil { return nil, err } - bytes := make([]byte, 4) - bytes[0] = m.PrecLevel - return append(data, bytes...), nil + copy(data, mbHdrBytes) + n += METER_BAND_HEADER_LEN + data[n] = m.PrecLevel + return } func (m *MeterBandDSCP) UnmarshalBinary(data []byte) error { @@ -129,22 +135,25 @@ func (m *MeterBandDSCP) UnmarshalBinary(data []byte) error { } type MeterBandExperimenter struct { - MeterBandHeader - Experimenter uint32 /* Experimenter ID which takes the same form as in struct ofp_experimenter_header. */ + MeterBandHeader /* Type: OFPMBT13_EXPERIMENTER. */ + Experimenter uint32 /* Experimenter ID which takes the same form as in struct ofp_experimenter_header. */ } func (m *MeterBandExperimenter) Len() (n uint16) { - return m.MeterBandHeader.Len() + 4 + return METER_BAND_LEN } func (m *MeterBandExperimenter) MarshalBinary() (data []byte, err error) { - data, err = m.MeterBandHeader.MarshalBinary() + data = make([]byte, m.Len()) + n := 0 + mbHdrBytes, err := m.MeterBandHeader.MarshalBinary() if err != nil { return nil, err } - bytes := make([]byte, 4) - binary.BigEndian.PutUint32(bytes, m.Experimenter) - return append(data, bytes...), nil + copy(data, mbHdrBytes) + n += METER_BAND_HEADER_LEN + binary.BigEndian.PutUint32(data[n:], m.Experimenter) + return } func (m *MeterBandExperimenter) UnmarshalBinary(data []byte) error { @@ -170,10 +179,6 @@ func NewMeterMod() *MeterMod { m := new(MeterMod) m.Header = NewOfp13Header() m.Header.Type = Type_MeterMod - - m.Command = OFPMC_ADD - m.Flags = OFPMF13_PKTPS - m.MeterId = 1 m.MeterBands = make([]util.Message, 0) return m } @@ -199,22 +204,29 @@ func (m *MeterMod) Len() (n uint16) { func (m *MeterMod) MarshalBinary() (data []byte, err error) { m.Header.Length = m.Len() - data, err = m.Header.MarshalBinary() - - bytes := make([]byte, 8) + data = make([]byte, m.Len()) n := 0 - binary.BigEndian.PutUint16(bytes[n:], m.Command) + hdrBytes, err := m.Header.MarshalBinary() + if err != nil { + return nil, err + } + copy(data, hdrBytes) + n += int(m.Header.Len()) + binary.BigEndian.PutUint16(data[n:], m.Command) n += 2 - binary.BigEndian.PutUint16(bytes[n:], m.Flags) + binary.BigEndian.PutUint16(data[n:], m.Flags) n += 2 - binary.BigEndian.PutUint32(bytes[n:], m.MeterId) + binary.BigEndian.PutUint32(data[n:], m.MeterId) n += 4 - data = append(data, bytes...) for _, mb := range m.MeterBands { - bytes, err = mb.MarshalBinary() - data = append(data, bytes...) - log.Debugf("Metermod band: %v", bytes) + mbBytes, err := mb.MarshalBinary() + if err != nil { + return nil, err + } + copy(data[n:], mbBytes) + n += METER_BAND_LEN + log.Debugf("Metermod band: %v", mbBytes) } log.Debugf("Metermod(%d): %v", len(data), data)