packet/bgp: Refactor construction of FlowSpec rules string

This patch introduces String() functions for the flags and reserved
values related to the FlowSpec rules.
Also removes the unused types and functions.

Signed-off-by: IWASE Yusuke <[email protected]>
This commit is contained in:
IWASE Yusuke
2017-11-24 12:55:34 +09:00
parent 8e98018c75
commit 35c79d833f
2 changed files with 140 additions and 220 deletions
+33 -100
View File
@@ -3451,7 +3451,7 @@ func (p *flowSpecPrefix) Type() BGPFlowSpecType {
}
func (p *flowSpecPrefix) String() string {
return fmt.Sprintf("[%s:%s]", p.Type(), p.Prefix.String())
return fmt.Sprintf("[%s: %s]", p.Type(), p.Prefix.String())
}
func (p *flowSpecPrefix) MarshalJSON() ([]byte, error) {
@@ -3500,7 +3500,7 @@ func (p *flowSpecPrefix6) Type() BGPFlowSpecType {
}
func (p *flowSpecPrefix6) String() string {
return fmt.Sprintf("[%s:%s/%d]", p.Type(), p.Prefix.String(), p.Offset)
return fmt.Sprintf("[%s: %s/%d]", p.Type(), p.Prefix.String(), p.Offset)
}
func (p *flowSpecPrefix6) MarshalJSON() ([]byte, error) {
@@ -3578,7 +3578,7 @@ func (p *flowSpecMac) Type() BGPFlowSpecType {
}
func (p *flowSpecMac) String() string {
return fmt.Sprintf("[%s:%s]", p.Type(), p.Mac.String())
return fmt.Sprintf("[%s: %s]", p.Type(), p.Mac.String())
}
func (p *flowSpecMac) MarshalJSON() ([]byte, error) {
@@ -3715,7 +3715,7 @@ func (p *FlowSpecComponent) Serialize(options ...*MarshallingOption) ([]byte, er
func (p *FlowSpecComponent) Len(options ...*MarshallingOption) int {
l := 1
for _, item := range p.Items {
l += (item.Len() + 1)
l += item.Len() + 1
}
return l
}
@@ -3725,113 +3725,42 @@ func (p *FlowSpecComponent) Type() BGPFlowSpecType {
}
func formatRaw(op int, value int) string {
return fmt.Sprintf("op: %b, value: %d", op, value)
}
func formatNumericOp(op int) string {
var opstr string
if op&0x40 > 0 {
opstr = "&"
} else {
opstr = " "
}
if op&0x2 > 0 {
opstr += ">"
}
if op&0x4 > 0 {
opstr += "<"
}
if op&0x1 > 0 {
opstr += "="
}
return opstr
}
func formatNumericOpFrontQty(op int) string {
gtlteqOnly := op & 0x07
return fmt.Sprintf("%s", DECNumOpNameMap[DECNumOp(gtlteqOnly)])
}
func formatNumericOpBackLogic(op int) string {
andOrOnly := op & 0x40 // let's ignore the END bit to avoid having an E at the end of the string
return fmt.Sprintf("%s", DECLogicOpNameMap[DECLogicOp(andOrOnly)])
return fmt.Sprintf("op:%b,value:%d", op, value)
}
func formatNumeric(op int, value int) string {
gtlteqOnly := op & 0x07
if DECNumOp(gtlteqOnly) == DECNumOpValueMap[DECNumOpNameMap[DEC_NUM_OP_FALSE]] || DECNumOp(gtlteqOnly) == DECNumOpValueMap[DECNumOpNameMap[DEC_NUM_OP_TRUE]] {
return fmt.Sprintf("%s%s", formatNumericOpFrontQty(op), formatNumericOpBackLogic(op))
} else {
return fmt.Sprintf("%s%s%d", formatNumericOpBackLogic(op), formatNumericOpFrontQty(op), value)
cmpFlag := DECNumOp(op & 0x7) // lower 3 bits
if cmpFlag == DEC_NUM_OP_TRUE || cmpFlag == DEC_NUM_OP_FALSE {
// Omit value field
return DECNumOp(op).String()
}
return fmt.Sprint(DECNumOp(op).String(), strconv.Itoa(value))
}
func formatProto(op int, value int) string {
return fmt.Sprintf("%s%s%s", formatNumericOpFrontQty(op), Protocol(value).String(), formatNumericOpBackLogic(op))
cmpFlag := DECNumOp(op & 0x7) // lower 3 bits
if cmpFlag == DEC_NUM_OP_TRUE || cmpFlag == DEC_NUM_OP_FALSE {
// Omit value field
return DECNumOp(op).String()
}
return fmt.Sprint(DECNumOp(op).String(), Protocol(value).String())
}
func formatTCPFlag(op int, value int) string {
var retString string
if op&BITMASK_FLAG_OP_NOT > 0 {
retString = fmt.Sprintf("%s%s", retString, BitmaskFlagOpNameMap[BITMASK_FLAG_OP_NOT])
}
if op&BITMASK_FLAG_OP_MATCH > 0 {
retString = fmt.Sprintf("%s%s", retString, BitmaskFlagOpNameMap[BITMASK_FLAG_OP_MATCH])
}
// Prepare a sorted list of flags because map iterations does not happen
// in a consistent order in Golang.
vs := make([]int, 0)
for _, v := range TCPFlagValueMap {
vs = append(vs, int(v))
}
sort.Ints(vs)
for _, v := range vs {
if value&v > 0 {
retString = fmt.Sprintf("%s%s", retString, TCPFlagNameMap[TCPFlag(v)])
}
}
if op&BITMASK_FLAG_OP_AND > 0 {
retString = fmt.Sprintf("%s%s", BitmaskFlagOpNameMap[BITMASK_FLAG_OP_AND], retString)
} else { // default is or
retString = fmt.Sprintf("%s%s", BitmaskFlagOpNameMap[BITMASK_FLAG_OP_OR], retString)
}
return retString
return fmt.Sprint(BitmaskFlagOp(op).String(), TCPFlag(value).String())
}
func formatFragment(op int, value int) string {
var retString string
if op&BITMASK_FLAG_OP_NOT > 0 {
retString = fmt.Sprintf("%s%s", retString, BitmaskFlagOpNameMap[BITMASK_FLAG_OP_NOT])
}
if op&BITMASK_FLAG_OP_MATCH > 0 {
retString = fmt.Sprintf("%s%s", retString, BitmaskFlagOpNameMap[BITMASK_FLAG_OP_MATCH])
}
// Prepare a sorted list of flags because map iterations does not happen
// in a consistent order in Golang.
vs := make([]int, 0)
for _, v := range FragmentFlagValueMap {
vs = append(vs, int(v))
}
sort.Ints(vs)
for _, v := range vs {
if value&v > 0 {
retString = fmt.Sprintf("%s%s", retString, FragmentFlagNameMap[FragmentFlag(v)])
}
}
if op&BITMASK_FLAG_OP_AND > 0 {
retString = fmt.Sprintf("%s%s", BitmaskFlagOpNameMap[BITMASK_FLAG_OP_AND], retString)
} else { // default is or
retString = fmt.Sprintf("%s%s", BitmaskFlagOpNameMap[BITMASK_FLAG_OP_OR], retString)
}
return retString
return fmt.Sprint(BitmaskFlagOp(op).String(), FragmentFlag(value).String())
}
func formatEtherType(op int, value int) string {
return fmt.Sprintf("%s%s", formatNumericOp(op), EthernetType(value).String())
cmpFlag := DECNumOp(op & 0x7) // lower 3 bits
if cmpFlag == DEC_NUM_OP_TRUE || cmpFlag == DEC_NUM_OP_FALSE {
// Omit value field
return DECNumOp(op).String()
}
return fmt.Sprint(DECNumOp(op).String(), EthernetType(value).String())
}
var flowSpecFormatMap = map[BGPFlowSpecType]func(op int, value int) string{
@@ -3860,14 +3789,18 @@ var flowSpecFormatMap = map[BGPFlowSpecType]func(op int, value int) string{
func (p *FlowSpecComponent) String() string {
f := flowSpecFormatMap[FLOW_SPEC_TYPE_UNKNOWN]
if _, ok := flowSpecFormatMap[p.Type()]; ok {
f = flowSpecFormatMap[p.Type()]
if _, ok := flowSpecFormatMap[p.typ]; ok {
f = flowSpecFormatMap[p.typ]
}
buf := bytes.NewBuffer(make([]byte, 0, 32))
items := make([]string, 0, len(p.Items))
for _, i := range p.Items {
buf.WriteString(f(i.Op, i.Value))
items = append(items, f(i.Op, i.Value))
}
return fmt.Sprintf("[%s:%s]", p.typ, buf.String())
// Removes leading and tailing spaces
value := strings.TrimSpace(strings.Join(items, ""))
return fmt.Sprintf("[%s: %s]", p.typ, value)
}
func (p *FlowSpecComponent) MarshalJSON() ([]byte, error) {
+107 -120
View File
@@ -70,21 +70,6 @@ var ProtocolNameMap = map[Protocol]string{
SCTP: "sctp",
}
var ProtocolValueMap = map[string]Protocol{
ProtocolNameMap[ICMP]: ICMP,
ProtocolNameMap[IGMP]: IGMP,
ProtocolNameMap[TCP]: TCP,
ProtocolNameMap[EGP]: EGP,
ProtocolNameMap[IGP]: IGP,
ProtocolNameMap[UDP]: UDP,
ProtocolNameMap[RSVP]: RSVP,
ProtocolNameMap[GRE]: GRE,
ProtocolNameMap[OSPF]: OSPF,
ProtocolNameMap[IPIP]: IPIP,
ProtocolNameMap[PIM]: PIM,
ProtocolNameMap[SCTP]: SCTP,
}
func (p Protocol) String() string {
name, ok := ProtocolNameMap[p]
if !ok {
@@ -96,14 +81,15 @@ func (p Protocol) String() string {
type TCPFlag int
const (
TCP_FLAG_FIN = 0x01
TCP_FLAG_SYN = 0x02
TCP_FLAG_RST = 0x04
TCP_FLAG_PUSH = 0x08
TCP_FLAG_ACK = 0x10
TCP_FLAG_URGENT = 0x20
TCP_FLAG_ECE = 0x40
TCP_FLAG_CWR = 0x80
_ TCPFlag = iota
TCP_FLAG_FIN = 0x01
TCP_FLAG_SYN = 0x02
TCP_FLAG_RST = 0x04
TCP_FLAG_PUSH = 0x08
TCP_FLAG_ACK = 0x10
TCP_FLAG_URGENT = 0x20
TCP_FLAG_ECE = 0x40
TCP_FLAG_CWR = 0x80
)
var TCPFlagNameMap = map[TCPFlag]string{
@@ -117,25 +103,38 @@ var TCPFlagNameMap = map[TCPFlag]string{
TCP_FLAG_ECE: "E",
}
var TCPFlagValueMap = map[string]TCPFlag{
TCPFlagNameMap[TCP_FLAG_FIN]: TCP_FLAG_FIN,
TCPFlagNameMap[TCP_FLAG_SYN]: TCP_FLAG_SYN,
TCPFlagNameMap[TCP_FLAG_RST]: TCP_FLAG_RST,
TCPFlagNameMap[TCP_FLAG_PUSH]: TCP_FLAG_PUSH,
TCPFlagNameMap[TCP_FLAG_ACK]: TCP_FLAG_ACK,
TCPFlagNameMap[TCP_FLAG_URGENT]: TCP_FLAG_URGENT,
TCPFlagNameMap[TCP_FLAG_CWR]: TCP_FLAG_CWR,
TCPFlagNameMap[TCP_FLAG_ECE]: TCP_FLAG_ECE,
// Prepares a sorted list of flags because map iterations does not happen
// in a consistent order in Golang.
var TCPSortedFlags = []TCPFlag{
TCP_FLAG_FIN,
TCP_FLAG_SYN,
TCP_FLAG_RST,
TCP_FLAG_PUSH,
TCP_FLAG_ACK,
TCP_FLAG_URGENT,
TCP_FLAG_ECE,
TCP_FLAG_CWR,
}
func (f TCPFlag) String() string {
flags := make([]string, 0, len(TCPSortedFlags))
for _, v := range TCPSortedFlags {
if f&v > 0 {
flags = append(flags, TCPFlagNameMap[v])
}
}
return strings.Join(flags, "")
}
type BitmaskFlagOp int
const (
BITMASK_FLAG_OP_OR = 0x00
BITMASK_FLAG_OP_AND = 0x40
BITMASK_FLAG_OP_END = 0x80
BITMASK_FLAG_OP_NOT = 0x02
BITMASK_FLAG_OP_MATCH = 0x01
BITMASK_FLAG_OP_OR BitmaskFlagOp = iota
BITMASK_FLAG_OP_MATCH = 0x01
BITMASK_FLAG_OP_NOT = 0x02
BITMASK_FLAG_OP_NOT_MATCH = 0x03
BITMASK_FLAG_OP_AND = 0x40
BITMASK_FLAG_OP_END = 0x80
)
var BitmaskFlagOpNameMap = map[BitmaskFlagOp]string{
@@ -146,22 +145,30 @@ var BitmaskFlagOpNameMap = map[BitmaskFlagOp]string{
BITMASK_FLAG_OP_MATCH: "=",
}
var BitmaskFlagOpValueMap = map[string]BitmaskFlagOp{
BitmaskFlagOpNameMap[BITMASK_FLAG_OP_OR]: BITMASK_FLAG_OP_OR,
BitmaskFlagOpNameMap[BITMASK_FLAG_OP_AND]: BITMASK_FLAG_OP_AND,
BitmaskFlagOpNameMap[BITMASK_FLAG_OP_END]: BITMASK_FLAG_OP_END,
BitmaskFlagOpNameMap[BITMASK_FLAG_OP_NOT]: BITMASK_FLAG_OP_NOT,
BitmaskFlagOpNameMap[BITMASK_FLAG_OP_MATCH]: BITMASK_FLAG_OP_MATCH,
func (f BitmaskFlagOp) String() string {
ops := make([]string, 0)
if f&BITMASK_FLAG_OP_AND > 0 {
ops = append(ops, BitmaskFlagOpNameMap[BITMASK_FLAG_OP_AND])
} else {
ops = append(ops, BitmaskFlagOpNameMap[BITMASK_FLAG_OP_OR])
}
if f&BITMASK_FLAG_OP_NOT > 0 {
ops = append(ops, BitmaskFlagOpNameMap[BITMASK_FLAG_OP_NOT])
}
if f&BITMASK_FLAG_OP_MATCH > 0 {
ops = append(ops, BitmaskFlagOpNameMap[BITMASK_FLAG_OP_MATCH])
}
return strings.Join(ops, "")
}
type FragmentFlag int
const (
FRAG_FLAG_NOT = 0x00
FRAG_FLAG_DONT = 0x01
FRAG_FLAG_IS = 0x02
FRAG_FLAG_FIRST = 0x04
FRAG_FLAG_LAST = 0x08
FRAG_FLAG_NOT FragmentFlag = iota
FRAG_FLAG_DONT = 0x01
FRAG_FLAG_IS = 0x02
FRAG_FLAG_FIRST = 0x04
FRAG_FLAG_LAST = 0x08
)
var FragmentFlagNameMap = map[FragmentFlag]string{
@@ -172,25 +179,41 @@ var FragmentFlagNameMap = map[FragmentFlag]string{
FRAG_FLAG_LAST: "last-fragment",
}
var FragmentFlagValueMap = map[string]FragmentFlag{
FragmentFlagNameMap[FRAG_FLAG_NOT]: FRAG_FLAG_NOT,
FragmentFlagNameMap[FRAG_FLAG_DONT]: FRAG_FLAG_DONT,
FragmentFlagNameMap[FRAG_FLAG_IS]: FRAG_FLAG_IS,
FragmentFlagNameMap[FRAG_FLAG_FIRST]: FRAG_FLAG_FIRST,
FragmentFlagNameMap[FRAG_FLAG_LAST]: FRAG_FLAG_LAST,
// Prepares a sorted list of flags because map iterations does not happen
// in a consistent order in Golang.
var FragmentSortedFlags = []FragmentFlag{
FRAG_FLAG_NOT,
FRAG_FLAG_DONT,
FRAG_FLAG_IS,
FRAG_FLAG_FIRST,
FRAG_FLAG_LAST,
}
func (f FragmentFlag) String() string {
flags := make([]string, 0, len(FragmentSortedFlags))
for _, v := range FragmentSortedFlags {
if f&v > 0 {
flags = append(flags, FragmentFlagNameMap[v])
}
}
// Note: If multiple bits are set, joins them with "+".
return strings.Join(flags, "+")
}
type DECNumOp int
const (
DEC_NUM_OP_TRUE = 0x00 // true always with END bit set
DEC_NUM_OP_EQ = 0x01
DEC_NUM_OP_GT = 0x02
DEC_NUM_OP_GT_EQ = 0x03
DEC_NUM_OP_LT = 0x04
DEC_NUM_OP_LT_EQ = 0x05
DEC_NUM_OP_NOT_EQ = 0x06
DEC_NUM_OP_FALSE = 0x07 // true always with END bit set
DEC_NUM_OP_TRUE DECNumOp = iota // true always with END bit set
DEC_NUM_OP_EQ = 0x01
DEC_NUM_OP_GT = 0x02
DEC_NUM_OP_GT_EQ = 0x03
DEC_NUM_OP_LT = 0x04
DEC_NUM_OP_LT_EQ = 0x05
DEC_NUM_OP_NOT_EQ = 0x06
DEC_NUM_OP_FALSE = 0x07 // false always with END bit set
DEC_NUM_OP_OR = 0x00
DEC_NUM_OP_AND = 0x40
DEC_NUM_OP_END = 0x80
)
var DECNumOpNameMap = map[DECNumOp]string{
@@ -202,49 +225,31 @@ var DECNumOpNameMap = map[DECNumOp]string{
DEC_NUM_OP_LT_EQ: "<=",
DEC_NUM_OP_NOT_EQ: "!=",
DEC_NUM_OP_FALSE: "false",
//DEC_NUM_OP_OR: " ", // duplicate with DEC_NUM_OP_TRUE
DEC_NUM_OP_AND: "&",
DEC_NUM_OP_END: "E",
}
var DECNumOpValueMap = map[string]DECNumOp{
DECNumOpNameMap[DEC_NUM_OP_TRUE]: DEC_NUM_OP_TRUE,
DECNumOpNameMap[DEC_NUM_OP_EQ]: DEC_NUM_OP_EQ,
DECNumOpNameMap[DEC_NUM_OP_GT]: DEC_NUM_OP_GT,
DECNumOpNameMap[DEC_NUM_OP_GT_EQ]: DEC_NUM_OP_GT_EQ,
DECNumOpNameMap[DEC_NUM_OP_LT]: DEC_NUM_OP_LT,
DECNumOpNameMap[DEC_NUM_OP_LT_EQ]: DEC_NUM_OP_LT_EQ,
DECNumOpNameMap[DEC_NUM_OP_NOT_EQ]: DEC_NUM_OP_NOT_EQ,
DECNumOpNameMap[DEC_NUM_OP_FALSE]: DEC_NUM_OP_FALSE,
}
type DECLogicOp int
const (
DEC_LOGIC_OP_END = 0x80
DEC_LOGIC_OP_OR = 0x00
DEC_LOGIC_OP_AND = 0x40
)
var DECLogicOpNameMap = map[DECLogicOp]string{
DEC_LOGIC_OP_OR: " ",
DEC_LOGIC_OP_AND: "&",
DEC_LOGIC_OP_END: "E",
}
var DECLogicOpValueMap = map[string]DECLogicOp{
DECLogicOpNameMap[DEC_LOGIC_OP_OR]: DEC_LOGIC_OP_OR,
DECLogicOpNameMap[DEC_LOGIC_OP_AND]: DEC_LOGIC_OP_AND,
DECLogicOpNameMap[DEC_LOGIC_OP_END]: DEC_LOGIC_OP_END,
}
func (f TCPFlag) String() string {
ss := make([]string, 0, 6)
for _, v := range []TCPFlag{TCP_FLAG_FIN, TCP_FLAG_SYN, TCP_FLAG_RST, TCP_FLAG_PUSH, TCP_FLAG_ACK, TCP_FLAG_URGENT, TCP_FLAG_CWR, TCP_FLAG_ECE} {
if f&v > 0 {
ss = append(ss, TCPFlagNameMap[v])
func (f DECNumOp) String() string {
ops := make([]string, 0)
logicFlag := DECNumOp(f & 0xc0) // higher 2 bits
if logicFlag&DEC_NUM_OP_AND > 0 {
ops = append(ops, DECNumOpNameMap[DEC_NUM_OP_AND])
} else {
ops = append(ops, " ") // DEC_NUM_OP_OR
}
// Omits DEC_NUM_OP_END
cmpFlag := DECNumOp(f & 0x7) // lower 3 bits
for v, s := range DECNumOpNameMap {
if cmpFlag == v {
ops = append(ops, s)
break
}
}
return strings.Join(ss, "|")
return strings.Join(ops, "")
}
// Potentially taken from https://www.iana.org/assignments/ieee-802-numbers/ieee-802-numbers.xhtml
type EthernetType int
const (
@@ -281,27 +286,9 @@ var EthernetTypeNameMap = map[EthernetType]string{
LOOPBACK: "loopback",
}
var EthernetTypeValueMap = map[string]EthernetType{
EthernetTypeNameMap[IPv4]: IPv4,
EthernetTypeNameMap[ARP]: ARP,
EthernetTypeNameMap[RARP]: RARP,
EthernetTypeNameMap[VMTP]: VMTP,
EthernetTypeNameMap[APPLE_TALK]: APPLE_TALK,
EthernetTypeNameMap[AARP]: AARP,
EthernetTypeNameMap[IPX]: IPX,
EthernetTypeNameMap[SNMP]: SNMP,
EthernetTypeNameMap[NET_BIOS]: NET_BIOS,
EthernetTypeNameMap[XTP]: XTP,
EthernetTypeNameMap[IPv6]: IPv6,
EthernetTypeNameMap[PPPoE_DISCOVERY]: PPPoE_DISCOVERY,
EthernetTypeNameMap[PPPoE_SESSION]: PPPoE_SESSION,
EthernetTypeNameMap[LOOPBACK]: LOOPBACK,
}
func (t EthernetType) String() string {
n, ok := EthernetTypeNameMap[t]
if !ok {
return fmt.Sprintf("%d", t)
if name, ok := EthernetTypeNameMap[t]; ok {
return name
}
return n
return fmt.Sprintf("%d", t)
}