summaryrefslogtreecommitdiffhomepage
path: root/packet/bgp
diff options
context:
space:
mode:
authorIWASE Yusuke <iwase.yusuke0@gmail.com>2018-02-22 13:29:52 +0900
committerIWASE Yusuke <iwase.yusuke0@gmail.com>2018-02-22 15:19:08 +0900
commit89f40dfa4a015d000489a1ffa70824722e7eafed (patch)
tree347c403a2b4020c926fc162d009dfab42452d00a /packet/bgp
parent07275fba28e3c33530d0a4c96dab61e66c3df46f (diff)
packet/bgp: Flatten structure of OpaqueExtended
Currently, to instantiate sub types of the Opaque Extended Community, it is required to instantiate "OpaqueExtended" and its value type (e.g., "ValidationExtended" or "EncapExtended") and also specify its sub type. This can cause the confusion of the outer and inner (value) structures and the unmatch of the value structure and its sub type. This patch makes the "OpaqueExtended" into more flat structure and introduces "NewXxxExtended()" function to improve usability. Signed-off-by: IWASE Yusuke <iwase.yusuke0@gmail.com>
Diffstat (limited to 'packet/bgp')
-rw-r--r--packet/bgp/bgp.go304
-rw-r--r--packet/bgp/helper.go8
2 files changed, 197 insertions, 115 deletions
diff --git a/packet/bgp/bgp.go b/packet/bgp/bgp.go
index d59ce441..c013f23a 100644
--- a/packet/bgp/bgp.go
+++ b/packet/bgp/bgp.go
@@ -6319,22 +6319,19 @@ func NewFourOctetAsSpecificExtended(subtype ExtendedCommunityAttrSubType, as uin
func ParseExtendedCommunity(subtype ExtendedCommunityAttrSubType, com string) (ExtendedCommunityInterface, error) {
if subtype == EC_SUBTYPE_ORIGIN_VALIDATION {
- var value ValidationState
+ var state ValidationState
switch com {
case VALIDATION_STATE_VALID.String():
- value = VALIDATION_STATE_VALID
+ state = VALIDATION_STATE_VALID
case VALIDATION_STATE_NOT_FOUND.String():
- value = VALIDATION_STATE_NOT_FOUND
+ state = VALIDATION_STATE_NOT_FOUND
case VALIDATION_STATE_INVALID.String():
- value = VALIDATION_STATE_INVALID
+ state = VALIDATION_STATE_INVALID
default:
return nil, fmt.Errorf("invalid validation state")
}
- return &OpaqueExtended{
- SubType: EC_SUBTYPE_ORIGIN_VALIDATION,
- Value: &ValidationExtended{
- Value: value,
- },
+ return &ValidationExtended{
+ State: state,
}, nil
}
elems, err := parseRdAndRt(com)
@@ -6364,27 +6361,6 @@ func ParseRouteTarget(rt string) (ExtendedCommunityInterface, error) {
return ParseExtendedCommunity(EC_SUBTYPE_ROUTE_TARGET, rt)
}
-type OpaqueExtendedValueInterface interface {
- Serialize() ([]byte, error)
- String() string
-}
-
-type DefaultOpaqueExtendedValue struct {
- Value []byte
-}
-
-func (v *DefaultOpaqueExtendedValue) Serialize() ([]byte, error) {
- v.Value = v.Value[:7]
- return v.Value[:7], nil
-}
-
-func (v *DefaultOpaqueExtendedValue) String() string {
- buf := make([]byte, 8)
- copy(buf[1:], v.Value)
- d := binary.BigEndian.Uint64(buf)
- return fmt.Sprintf("%d", d)
-}
-
type ValidationState uint8
const (
@@ -6406,33 +6382,83 @@ func (s ValidationState) String() string {
}
type ValidationExtended struct {
- Value ValidationState
+ State ValidationState
}
func (e *ValidationExtended) Serialize() ([]byte, error) {
- buf := make([]byte, 7)
- buf[0] = byte(EC_SUBTYPE_ORIGIN_VALIDATION)
- buf[6] = byte(e.Value)
+ buf := make([]byte, 8, 8)
+ typ, subType := e.GetTypes()
+ buf[0] = byte(typ)
+ buf[1] = byte(subType)
+ buf[7] = byte(e.State)
return buf, nil
}
func (e *ValidationExtended) String() string {
- return e.Value.String()
+ return e.State.String()
+}
+
+func (e *ValidationExtended) GetTypes() (ExtendedCommunityAttrType, ExtendedCommunityAttrSubType) {
+ return EC_TYPE_NON_TRANSITIVE_OPAQUE, EC_SUBTYPE_ORIGIN_VALIDATION
+}
+
+func (e *ValidationExtended) MarshalJSON() ([]byte, error) {
+ t, s := e.GetTypes()
+ return json.Marshal(struct {
+ Type ExtendedCommunityAttrType `json:"type"`
+ SubType ExtendedCommunityAttrSubType `json:"subtype"`
+ State ValidationState `json:"value"`
+ }{
+ Type: t,
+ SubType: s,
+ State: e.State,
+ })
+}
+
+func NewValidationExtended(state ValidationState) *ValidationExtended {
+ return &ValidationExtended{
+ State: state,
+ }
}
type ColorExtended struct {
- Value uint32
+ Color uint32
}
func (e *ColorExtended) Serialize() ([]byte, error) {
- buf := make([]byte, 7)
- buf[0] = byte(EC_SUBTYPE_COLOR)
- binary.BigEndian.PutUint32(buf[3:], uint32(e.Value))
+ buf := make([]byte, 8, 8)
+ typ, subType := e.GetTypes()
+ buf[0] = byte(typ)
+ buf[1] = byte(subType)
+ binary.BigEndian.PutUint32(buf[4:8], uint32(e.Color))
return buf, nil
}
func (e *ColorExtended) String() string {
- return fmt.Sprintf("%d", e.Value)
+ return fmt.Sprintf("%d", e.Color)
+}
+
+func (e *ColorExtended) GetTypes() (ExtendedCommunityAttrType, ExtendedCommunityAttrSubType) {
+ return EC_TYPE_TRANSITIVE_OPAQUE, EC_SUBTYPE_COLOR
+}
+
+func (e *ColorExtended) MarshalJSON() ([]byte, error) {
+ t, s := e.GetTypes()
+ return json.Marshal(struct {
+ Type ExtendedCommunityAttrType `json:"type"`
+ SubType ExtendedCommunityAttrSubType `json:"subtype"`
+ Color uint32 `json:"color"`
+ }{
+ Type: t,
+ SubType: s,
+ Color: e.Color,
+ })
+}
+
+func NewColorExtended(color uint32) *ColorExtended {
+ return &ColorExtended{
+ Color: color,
+ }
}
type EncapExtended struct {
@@ -6440,9 +6466,11 @@ type EncapExtended struct {
}
func (e *EncapExtended) Serialize() ([]byte, error) {
- buf := make([]byte, 7)
- buf[0] = byte(EC_SUBTYPE_ENCAPSULATION)
- binary.BigEndian.PutUint16(buf[5:], uint16(e.TunnelType))
+ buf := make([]byte, 8, 8)
+ typ, subType := e.GetTypes()
+ buf[0] = byte(typ)
+ buf[1] = byte(subType)
+ binary.BigEndian.PutUint16(buf[6:8], uint16(e.TunnelType))
return buf, nil
}
@@ -6471,12 +6499,37 @@ func (e *EncapExtended) String() string {
}
}
+func (e *EncapExtended) GetTypes() (ExtendedCommunityAttrType, ExtendedCommunityAttrSubType) {
+ return EC_TYPE_TRANSITIVE_OPAQUE, EC_SUBTYPE_ENCAPSULATION
+}
+
+func (e *EncapExtended) MarshalJSON() ([]byte, error) {
+ t, s := e.GetTypes()
+ return json.Marshal(struct {
+ Type ExtendedCommunityAttrType `json:"type"`
+ SubType ExtendedCommunityAttrSubType `json:"subtype"`
+ TunnelType TunnelType `json:"tunnel_type"`
+ }{
+ Type: t,
+ SubType: s,
+ TunnelType: e.TunnelType,
+ })
+}
+
+func NewEncapExtended(tunnelType TunnelType) *EncapExtended {
+ return &EncapExtended{
+ TunnelType: tunnelType,
+ }
+}
+
type DefaultGatewayExtended struct {
}
func (e *DefaultGatewayExtended) Serialize() ([]byte, error) {
- buf := make([]byte, 7)
- buf[0] = byte(EC_SUBTYPE_DEFAULT_GATEWAY)
+ buf := make([]byte, 8, 8)
+ typ, subType := e.GetTypes()
+ buf[0] = byte(typ)
+ buf[1] = byte(subType)
return buf, nil
}
@@ -6484,70 +6537,60 @@ func (e *DefaultGatewayExtended) String() string {
return "default-gateway"
}
-type OpaqueExtended struct {
- IsTransitive bool
- Value OpaqueExtendedValueInterface
- SubType ExtendedCommunityAttrSubType
+func (e *DefaultGatewayExtended) GetTypes() (ExtendedCommunityAttrType, ExtendedCommunityAttrSubType) {
+ return EC_TYPE_TRANSITIVE_OPAQUE, EC_SUBTYPE_DEFAULT_GATEWAY
}
-func (e *OpaqueExtended) DecodeFromBytes(data []byte) error {
- if len(data) != 7 {
- return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("Invalid OpaqueExtended bytes len: %d", len(data)))
- }
- e.SubType = ExtendedCommunityAttrSubType(data[0])
+func (e *DefaultGatewayExtended) MarshalJSON() ([]byte, error) {
+ t, s := e.GetTypes()
+ return json.Marshal(struct {
+ Type ExtendedCommunityAttrType `json:"type"`
+ SubType ExtendedCommunityAttrSubType `json:"subtype"`
+ }{
+ Type: t,
+ SubType: s,
+ })
+}
- if e.IsTransitive {
- switch e.SubType {
- case EC_SUBTYPE_COLOR:
- v := binary.BigEndian.Uint32(data[3:7])
- e.Value = &ColorExtended{
- Value: v,
- }
- case EC_SUBTYPE_ENCAPSULATION:
- t := TunnelType(binary.BigEndian.Uint16(data[5:7]))
- e.Value = &EncapExtended{
- TunnelType: t,
- }
- case EC_SUBTYPE_DEFAULT_GATEWAY:
- e.Value = &DefaultGatewayExtended{}
- default:
- e.Value = &DefaultOpaqueExtendedValue{
- Value: data, //7byte
- }
- }
- } else {
- switch e.SubType {
- case EC_SUBTYPE_ORIGIN_VALIDATION:
- e.Value = &ValidationExtended{
- Value: ValidationState(data[6]),
- }
- default:
- e.Value = &DefaultOpaqueExtendedValue{
- Value: data, //7byte
- }
- }
- }
- return nil
+func NewDefaultGatewayExtended() *DefaultGatewayExtended {
+ return &DefaultGatewayExtended{}
+}
+
+type OpaqueExtended struct {
+ IsTransitive bool
+ Value []byte
}
func (e *OpaqueExtended) Serialize() ([]byte, error) {
- buf := make([]byte, 1, 7)
+ if len(e.Value) != 7 {
+ return nil, fmt.Errorf("invalid value length for opaque extended community: %d", len(e.Value))
+ }
+ buf := make([]byte, 8, 8)
if e.IsTransitive {
buf[0] = byte(EC_TYPE_TRANSITIVE_OPAQUE)
} else {
buf[0] = byte(EC_TYPE_NON_TRANSITIVE_OPAQUE)
}
- bbuf, err := e.Value.Serialize()
- e.SubType = ExtendedCommunityAttrSubType(bbuf[0])
- if err != nil {
- return nil, err
- }
- buf = append(buf, bbuf...)
+ copy(buf[1:], e.Value)
return buf, nil
}
func (e *OpaqueExtended) String() string {
- return e.Value.String()
+ buf := make([]byte, 8, 8)
+ copy(buf[1:], e.Value)
+ return fmt.Sprintf("%d", binary.BigEndian.Uint64(buf))
+}
+
+func (e *OpaqueExtended) GetTypes() (ExtendedCommunityAttrType, ExtendedCommunityAttrSubType) {
+ var subType ExtendedCommunityAttrSubType
+ if len(e.Value) > 0 {
+ // Use the first byte of value as the sub type
+ subType = ExtendedCommunityAttrSubType(e.Value[0])
+ }
+ if e.IsTransitive {
+ return EC_TYPE_TRANSITIVE_OPAQUE, subType
+ }
+ return EC_TYPE_NON_TRANSITIVE_OPAQUE, subType
}
func (e *OpaqueExtended) MarshalJSON() ([]byte, error) {
@@ -6555,7 +6598,7 @@ func (e *OpaqueExtended) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
Type ExtendedCommunityAttrType `json:"type"`
Subtype ExtendedCommunityAttrSubType `json:"subtype"`
- Value OpaqueExtendedValueInterface `json:"value"`
+ Value []byte `json:"value"`
}{
Type: t,
Subtype: s,
@@ -6563,18 +6606,50 @@ func (e *OpaqueExtended) MarshalJSON() ([]byte, error) {
})
}
-func (e *OpaqueExtended) GetTypes() (ExtendedCommunityAttrType, ExtendedCommunityAttrSubType) {
- t := EC_TYPE_TRANSITIVE_OPAQUE
- if !e.IsTransitive {
- t = EC_TYPE_NON_TRANSITIVE_OPAQUE
+func NewOpaqueExtended(isTransitive bool, value []byte) *OpaqueExtended {
+ v := make([]byte, 7, 7)
+ copy(v, value)
+ return &OpaqueExtended{
+ IsTransitive: isTransitive,
+ Value: v,
}
- return t, e.SubType
}
-func NewOpaqueExtended(isTransitive bool) *OpaqueExtended {
- return &OpaqueExtended{
- IsTransitive: isTransitive,
+func parseOpaqueExtended(data []byte) (ExtendedCommunityInterface, error) {
+ typ := ExtendedCommunityAttrType(data[0])
+ isTransitive := false
+ switch typ {
+ case EC_TYPE_TRANSITIVE_OPAQUE:
+ isTransitive = true
+ case EC_TYPE_NON_TRANSITIVE_OPAQUE:
+ // isTransitive = false
+ default:
+ return nil, NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("invalid opaque extended community type: %d", data[0]))
}
+ subType := ExtendedCommunityAttrSubType(data[1])
+
+ if isTransitive {
+ switch subType {
+ case EC_SUBTYPE_COLOR:
+ return &ColorExtended{
+ Color: binary.BigEndian.Uint32(data[4:8]),
+ }, nil
+ case EC_SUBTYPE_ENCAPSULATION:
+ return &EncapExtended{
+ TunnelType: TunnelType(binary.BigEndian.Uint16(data[6:8])),
+ }, nil
+ case EC_SUBTYPE_DEFAULT_GATEWAY:
+ return &DefaultGatewayExtended{}, nil
+ }
+ } else {
+ switch subType {
+ case EC_SUBTYPE_ORIGIN_VALIDATION:
+ return &ValidationExtended{
+ State: ValidationState(data[7]),
+ }, nil
+ }
+ }
+ return NewOpaqueExtended(isTransitive, data[1:8]), nil
}
type ESILabelExtended struct {
@@ -7211,9 +7286,7 @@ func ParseExtended(data []byte) (ExtendedCommunityInterface, error) {
transitive = true
fallthrough
case EC_TYPE_NON_TRANSITIVE_OPAQUE:
- e := NewOpaqueExtended(transitive)
- err := e.DecodeFromBytes(data[1:8])
- return e, err
+ return parseOpaqueExtended(data)
case EC_TYPE_EVPN:
return parseEvpnExtended(data)
case EC_TYPE_GENERIC_TRANSITIVE_EXPERIMENTAL, EC_TYPE_GENERIC_TRANSITIVE_EXPERIMENTAL2, EC_TYPE_GENERIC_TRANSITIVE_EXPERIMENTAL3:
@@ -8956,10 +9029,23 @@ func (e *TwoOctetAsSpecificExtended) Flat() map[string]string {
return map[string]string{}
}
+func (e *ColorExtended) Flat() map[string]string {
+ return map[string]string{}
+}
+
+func (e *EncapExtended) Flat() map[string]string {
+ return map[string]string{"encaspulation": e.TunnelType.String()}
+}
+
+func (e *DefaultGatewayExtended) Flat() map[string]string {
+ return map[string]string{}
+}
+
+func (e *ValidationExtended) Flat() map[string]string {
+ return map[string]string{}
+}
+
func (e *OpaqueExtended) Flat() map[string]string {
- if e.SubType == EC_SUBTYPE_ENCAPSULATION {
- return map[string]string{"encaspulation": e.Value.String()}
- }
return map[string]string{}
}
diff --git a/packet/bgp/helper.go b/packet/bgp/helper.go
index 79229d92..851332fd 100644
--- a/packet/bgp/helper.go
+++ b/packet/bgp/helper.go
@@ -65,12 +65,8 @@ func NewTestBGPUpdateMessage() *BGPMessage {
NewTwoOctetAsSpecificExtended(EC_SUBTYPE_ROUTE_TARGET, 10003, 3<<20, isTransitive),
NewFourOctetAsSpecificExtended(EC_SUBTYPE_ROUTE_TARGET, 1<<20, 300, isTransitive),
NewIPv4AddressSpecificExtended(EC_SUBTYPE_ROUTE_TARGET, "192.2.1.2", 3000, isTransitive),
- &OpaqueExtended{
- Value: &DefaultOpaqueExtendedValue{[]byte{255, 1, 2, 3, 4, 5, 6, 7}},
- },
- &OpaqueExtended{
- Value: &ValidationExtended{Value: VALIDATION_STATE_INVALID},
- },
+ NewOpaqueExtended(false, []byte{1, 2, 3, 4, 5, 6, 7}),
+ NewValidationExtended(VALIDATION_STATE_INVALID),
&UnknownExtended{Type: 99, Value: []byte{0, 1, 2, 3, 4, 5, 6, 7}},
NewESILabelExtended(1000, true),
NewESImportRouteTarget("11:22:33:44:55:66"),