summaryrefslogtreecommitdiffhomepage
path: root/table/message.go
diff options
context:
space:
mode:
authorISHIDA Wataru <ishida.wataru@lab.ntt.co.jp>2015-12-25 01:48:03 +0900
committerFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2015-12-25 20:20:13 -0800
commitfdaa6da2cdbc85f2a6be942556dfdc2f489a1175 (patch)
tree820aec92c5a35bfe2abb49ddd9c19eea9e7b8a39 /table/message.go
parent3184c7691c93a59e7a6abba916b97d364c36c7ae (diff)
table: fix UpdatePathAttrs2ByteAs and UpdatePathAttrs4ByteAs
Diffstat (limited to 'table/message.go')
-rw-r--r--table/message.go173
1 files changed, 123 insertions, 50 deletions
diff --git a/table/message.go b/table/message.go
index ee31f18d..ad44a88f 100644
--- a/table/message.go
+++ b/table/message.go
@@ -17,6 +17,7 @@ package table
import (
"bytes"
+ log "github.com/Sirupsen/logrus"
"github.com/osrg/gobgp/packet"
"hash/fnv"
)
@@ -25,10 +26,10 @@ func UpdatePathAttrs2ByteAs(msg *bgp.BGPUpdate) error {
var asAttr *bgp.PathAttributeAsPath
idx := 0
for i, attr := range msg.PathAttributes {
- switch attr.(type) {
- case *bgp.PathAttributeAsPath:
- asAttr = attr.(*bgp.PathAttributeAsPath)
+ if a, ok := attr.(*bgp.PathAttributeAsPath); ok {
+ asAttr = a
idx = i
+ break
}
}
@@ -36,89 +37,161 @@ func UpdatePathAttrs2ByteAs(msg *bgp.BGPUpdate) error {
return nil
}
- msg.PathAttributes = cloneAttrSlice(msg.PathAttributes)
- asAttr = msg.PathAttributes[idx].(*bgp.PathAttributeAsPath)
- as4pathParam := make([]*bgp.As4PathParam, 0)
- newASparams := make([]bgp.AsPathParamInterface, len(asAttr.Value))
- for i, param := range asAttr.Value {
- asParam := param.(*bgp.As4PathParam)
-
- newAs := make([]uint32, 0)
- oldAs := make([]uint16, len(asParam.AS))
- for j := 0; j < len(asParam.AS); j++ {
- if asParam.AS[j] > (1<<16)-1 {
- oldAs[j] = bgp.AS_TRANS
- newAs = append(newAs, asParam.AS[j])
+ as4Params := make([]*bgp.As4PathParam, 0, len(asAttr.Value))
+ as2Params := make([]bgp.AsPathParamInterface, 0, len(asAttr.Value))
+ mkAs4 := false
+ for _, param := range asAttr.Value {
+ as4Param := param.(*bgp.As4PathParam)
+ as2Path := make([]uint16, 0, len(as4Param.AS))
+ for _, as := range as4Param.AS {
+ if as > (1<<16)-1 {
+ mkAs4 = true
+ as2Path = append(as2Path, bgp.AS_TRANS)
} else {
- oldAs[j] = uint16(asParam.AS[j])
+ as2Path = append(as2Path, uint16(as))
}
}
+ as2Params = append(as2Params, bgp.NewAsPathParam(as4Param.Type, as2Path))
- newASparams[i] = bgp.NewAsPathParam(asParam.Type, oldAs)
- if len(newAs) > 0 {
- as4pathParam = append(as4pathParam, bgp.NewAs4PathParam(asParam.Type, newAs))
+ // RFC 6793 4.2.2 Generating Updates
+ //
+ // Whenever the AS path information contains the AS_CONFED_SEQUENCE or
+ // AS_CONFED_SET path segment, the NEW BGP speaker MUST exclude such
+ // path segments from the AS4_PATH attribute being constructed.
+ if as4Param.Type != bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SEQ && as4Param.Type != bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SET {
+ as4Params = append(as4Params, as4Param)
}
}
- msg.PathAttributes[idx] = bgp.NewPathAttributeAsPath(newASparams)
- if len(as4pathParam) > 0 {
- msg.PathAttributes = append(msg.PathAttributes, bgp.NewPathAttributeAs4Path(as4pathParam))
+ msg.PathAttributes[idx] = bgp.NewPathAttributeAsPath(as2Params)
+ if mkAs4 {
+ msg.PathAttributes = append(msg.PathAttributes, bgp.NewPathAttributeAs4Path(as4Params))
}
return nil
}
func UpdatePathAttrs4ByteAs(msg *bgp.BGPUpdate) error {
- newPathAttrs := make([]bgp.PathAttributeInterface, 0)
var asAttr *bgp.PathAttributeAsPath
var as4Attr *bgp.PathAttributeAs4Path
-
- for _, attr := range msg.PathAttributes {
+ asAttrPos := 0
+ as4AttrPos := 0
+ for i, attr := range msg.PathAttributes {
switch attr.(type) {
case *bgp.PathAttributeAsPath:
asAttr = attr.(*bgp.PathAttributeAsPath)
- newPathAttrs = append(newPathAttrs, attr)
+ for j, param := range asAttr.Value {
+ as2Param, ok := param.(*bgp.AsPathParam)
+ if ok {
+ asPath := make([]uint32, 0, len(as2Param.AS))
+ for _, as := range as2Param.AS {
+ asPath = append(asPath, uint32(as))
+ }
+ as4Param := bgp.NewAs4PathParam(as2Param.Type, asPath)
+ asAttr.Value[j] = as4Param
+ }
+ }
+ asAttrPos = i
+ msg.PathAttributes[i] = asAttr
case *bgp.PathAttributeAs4Path:
+ as4AttrPos = i
as4Attr = attr.(*bgp.PathAttributeAs4Path)
- default:
- newPathAttrs = append(newPathAttrs, attr)
}
}
- if asAttr == nil {
+ if as4Attr != nil {
+ msg.PathAttributes = append(msg.PathAttributes[:as4AttrPos], msg.PathAttributes[as4AttrPos+1:]...)
+ }
+
+ if asAttr == nil || as4Attr == nil {
return nil
}
- AS := make([]uint32, 0)
+ asLen := 0
+ asConfedLen := 0
+ asParams := make([]*bgp.As4PathParam, 0, len(asAttr.Value))
+ for _, param := range asAttr.Value {
+ asLen += param.ASLen()
+ p := param.(*bgp.As4PathParam)
+ switch p.Type {
+ case bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SET:
+ asConfedLen += 1
+ case bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SEQ:
+ asConfedLen += len(p.AS)
+ }
+ asParams = append(asParams, p)
+ }
+
+ as4Len := 0
+ as4Params := make([]*bgp.As4PathParam, 0, len(as4Attr.Value))
if as4Attr != nil {
for _, p := range as4Attr.Value {
- AS = append(AS, p.AS...)
+ // RFC 6793 6. Error Handling
+ //
+ // the path segment types AS_CONFED_SEQUENCE and AS_CONFED_SET [RFC5065]
+ // MUST NOT be carried in the AS4_PATH attribute of an UPDATE message.
+ // A NEW BGP speaker that receives these path segment types in the AS4_PATH
+ // attribute of an UPDATE message from an OLD BGP speaker MUST discard
+ // these path segments, adjust the relevant attribute fields accordingly,
+ // and continue processing the UPDATE message.
+ // This case SHOULD be logged locally for analysis.
+ switch p.Type {
+ case bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SEQ, bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SET:
+ typ := "CONFED_SEQ"
+ if p.Type == bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SET {
+ typ = "CONFED_SET"
+ }
+ log.Warnf("AS4_PATH contains %s segment %s. ignore", typ, p.String())
+ continue
+ }
+ as4Len += p.ASLen()
+ as4Params = append(as4Params, p)
}
- msg.PathAttributes = newPathAttrs
}
- transIdx := 0
- for i, param := range asAttr.Value {
- asParam, y := param.(*bgp.AsPathParam)
- if !y {
- continue
+ if asLen+asConfedLen < as4Len {
+ log.Warnf("AS4_PATH is longer than AS_PATH. ignore AS4_PATH")
+ return nil
+ }
+
+ keepNum := asLen + asConfedLen - as4Len
+
+ newParams := make([]*bgp.As4PathParam, 0, len(asAttr.Value))
+ for _, param := range asParams {
+ if keepNum-param.ASLen() >= 0 {
+ newParams = append(newParams, param)
+ keepNum -= param.ASLen()
+ } else {
+ // only SEQ param reaches here
+ param.AS = param.AS[:keepNum]
+ newParams = append(newParams, param)
+ keepNum = 0
}
- newAS := make([]uint32, len(asParam.AS))
- for j := 0; j < len(asParam.AS); j++ {
- if asParam.AS[j] == bgp.AS_TRANS {
- if transIdx == len(AS) {
- //return error
- }
- newAS[j] = AS[transIdx]
- transIdx++
+ if keepNum <= 0 {
+ break
+ }
+ }
+
+ for _, param := range as4Params {
+ lastParam := newParams[len(newParams)-1]
+ if param.Type == lastParam.Type && param.Type == bgp.BGP_ASPATH_ATTR_TYPE_SEQ {
+ if len(lastParam.AS)+len(param.AS) > 255 {
+ lastParam.AS = append(lastParam.AS, param.AS[:255-len(lastParam.AS)]...)
+ param.AS = param.AS[255-len(lastParam.AS):]
+ newParams = append(newParams, param)
} else {
- newAS[j] = uint32(asParam.AS[j])
+ lastParam.AS = append(lastParam.AS, param.AS...)
}
+ } else {
+ newParams = append(newParams, param)
}
- asAttr.Value[i] = bgp.NewAs4PathParam(asParam.Type, newAS)
}
- if len(AS) != transIdx {
- //return error
+
+ newIntfParams := make([]bgp.AsPathParamInterface, 0, len(asAttr.Value))
+ for _, p := range newParams {
+ newIntfParams = append(newIntfParams, p)
}
+
+ msg.PathAttributes[asAttrPos] = bgp.NewPathAttributeAsPath(newIntfParams)
return nil
}