diff options
-rw-r--r-- | gobgp/cmd/neighbor.go | 8 | ||||
-rw-r--r-- | packet/bgp/bgp.go | 22 | ||||
-rw-r--r-- | packet/bgp/validate.go | 17 | ||||
-rw-r--r-- | server/fsm.go | 6 | ||||
-rw-r--r-- | server/rpki.go | 9 | ||||
-rw-r--r-- | table/destination.go | 15 | ||||
-rw-r--r-- | table/message.go | 48 | ||||
-rw-r--r-- | table/path.go | 85 |
8 files changed, 119 insertions, 91 deletions
diff --git a/gobgp/cmd/neighbor.go b/gobgp/cmd/neighbor.go index 7414c17c..edcb11bf 100644 --- a/gobgp/cmd/neighbor.go +++ b/gobgp/cmd/neighbor.go @@ -565,8 +565,8 @@ func checkOriginAsWasNotShown(p *table.Path, shownAs map[uint32]struct{}) bool { if len(asPath) == 0 { return false } - aslist := asPath[len(asPath)-1].(*bgp.As4PathParam).AS - origin := aslist[len(aslist)-1] + asList := asPath[len(asPath)-1].GetAS() + origin := asList[len(asList)-1] if _, ok := shownAs[origin]; ok { return false @@ -585,8 +585,8 @@ func showValidationInfo(p *table.Path, shownAs map[uint32]struct{}) error { status := p.Validation().Status reason := p.Validation().Reason - aslist := asPath[len(asPath)-1].(*bgp.As4PathParam).AS - origin := aslist[len(aslist)-1] + asList := asPath[len(asPath)-1].GetAS() + origin := asList[len(asList)-1] fmt.Printf("Target Prefix: %s, AS: %d\n", p.GetNlri().String(), origin) fmt.Printf(" This route is %s", status) diff --git a/packet/bgp/bgp.go b/packet/bgp/bgp.go index 2fea8b44..ef2e3e20 100644 --- a/packet/bgp/bgp.go +++ b/packet/bgp/bgp.go @@ -5213,6 +5213,8 @@ var asPathParamFormatMap = map[uint8]*AsPathParamFormat{ } type AsPathParamInterface interface { + GetType() uint8 + GetAS() []uint32 Serialize() ([]byte, error) DecodeFromBytes([]byte) error Len() int @@ -5227,6 +5229,18 @@ type AsPathParam struct { AS []uint16 } +func (a *AsPathParam) GetType() uint8 { + return a.Type +} + +func (a *AsPathParam) GetAS() []uint32 { + nums := make([]uint32, 0, len(a.AS)) + for _, as := range a.AS { + nums = append(nums, uint32(as)) + } + return nums +} + func (a *AsPathParam) Serialize() ([]byte, error) { buf := make([]byte, 2+len(a.AS)*2) buf[0] = uint8(a.Type) @@ -5314,6 +5328,14 @@ type As4PathParam struct { AS []uint32 } +func (a *As4PathParam) GetType() uint8 { + return a.Type +} + +func (a *As4PathParam) GetAS() []uint32 { + return a.AS +} + func (a *As4PathParam) Serialize() ([]byte, error) { buf := make([]byte, 2+len(a.AS)*4) buf[0] = a.Type diff --git a/packet/bgp/validate.go b/packet/bgp/validate.go index ecc67067..1b8f27c9 100644 --- a/packet/bgp/validate.go +++ b/packet/bgp/validate.go @@ -173,23 +173,16 @@ func ValidateAttribute(a PathAttributeInterface, rfs map[RouteFamily]BGPAddPathM } } case *PathAttributeAsPath: - getSegType := func(p AsPathParamInterface) uint8 { - asParam, y := p.(*As4PathParam) - if y { - return asParam.Type - } else { - return p.(*AsPathParam).Type - } - } if isEBGP { if isConfed { - if segType := getSegType(p.Value[0]); segType != BGP_ASPATH_ATTR_TYPE_CONFED_SEQ { + if segType := p.Value[0].GetType(); segType != BGP_ASPATH_ATTR_TYPE_CONFED_SEQ { return false, NewMessageError(eCode, eSubCodeMalformedAspath, nil, fmt.Sprintf("segment type is not confederation seq (%d)", segType)) } } else { - for _, paramIf := range p.Value { - segType := getSegType(paramIf) - if segType == BGP_ASPATH_ATTR_TYPE_CONFED_SET || segType == BGP_ASPATH_ATTR_TYPE_CONFED_SEQ { + for _, param := range p.Value { + segType := param.GetType() + switch segType { + case BGP_ASPATH_ATTR_TYPE_CONFED_SET, BGP_ASPATH_ATTR_TYPE_CONFED_SEQ: err := NewMessageErrorWithErrorHandling( eCode, eSubCodeMalformedAspath, nil, getErrorHandlingFromPathAttribute(p.GetType()), nil, fmt.Sprintf("segment type confederation(%d) found", segType)) if err.(*MessageError).Stronger(strongestError) { diff --git a/server/fsm.go b/server/fsm.go index 2c2128cb..c121c85f 100644 --- a/server/fsm.go +++ b/server/fsm.go @@ -677,10 +677,10 @@ func getPathAttrFromBGPUpdate(m *bgp.BGPUpdate, typ bgp.BGPAttrType) bgp.PathAtt return nil } -func hasOwnASLoop(ownAS uint32, limit int, aspath *bgp.PathAttributeAsPath) bool { +func hasOwnASLoop(ownAS uint32, limit int, asPath *bgp.PathAttributeAsPath) bool { cnt := 0 - for _, i := range aspath.Value { - for _, as := range i.(*bgp.As4PathParam).AS { + for _, param := range asPath.Value { + for _, as := range param.GetAS() { if as == ownAS { cnt++ if cnt > limit { diff --git a/server/rpki.go b/server/rpki.go index 8f286930..75f25409 100644 --- a/server/rpki.go +++ b/server/rpki.go @@ -511,13 +511,14 @@ func ValidatePath(ownAs uint32, tree *radix.Tree, cidr string, asPath *bgp.PathA if asPath == nil || len(asPath.Value) == 0 { as = ownAs } else { - asParam := asPath.Value[len(asPath.Value)-1].(*bgp.As4PathParam) - switch asParam.Type { + param := asPath.Value[len(asPath.Value)-1] + switch param.GetType() { case bgp.BGP_ASPATH_ATTR_TYPE_SEQ: - if len(asParam.AS) == 0 { + asList := param.GetAS() + if len(asList) == 0 { as = ownAs } else { - as = asParam.AS[len(asParam.AS)-1] + as = asList[len(asList)-1] } case bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SET, bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SEQ: as = ownAs diff --git a/table/destination.go b/table/destination.go index f9ed3509..fd32371d 100644 --- a/table/destination.go +++ b/table/destination.go @@ -861,17 +861,18 @@ func compareByMED(path1, path2 *Path) *Path { isSameAS := func() bool { firstAS := func(path *Path) uint32 { - if aspath := path.GetAsPath(); aspath != nil { - asPathParam := aspath.Value - for i := 0; i < len(asPathParam); i++ { - asPath := asPathParam[i].(*bgp.As4PathParam) - if asPath.Num == 0 { + if asPath := path.GetAsPath(); asPath != nil { + for _, v := range asPath.Value { + segType := v.GetType() + asList := v.GetAS() + if len(asList) == 0 { continue } - if asPath.Type == bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SET || asPath.Type == bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SEQ { + switch segType { + case bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SET, bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SEQ: continue } - return asPath.AS[0] + return asList[0] } } return 0 diff --git a/table/message.go b/table/message.go index 0909d08f..a7195ac6 100644 --- a/table/message.go +++ b/table/message.go @@ -45,9 +45,10 @@ func UpdatePathAttrs2ByteAs(msg *bgp.BGPUpdate) error { 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 { + segType := param.GetType() + asList := param.GetAS() + as2Path := make([]uint16, 0, len(asList)) + for _, as := range asList { if as > (1<<16)-1 { mkAs4 = true as2Path = append(as2Path, bgp.AS_TRANS) @@ -55,15 +56,20 @@ func UpdatePathAttrs2ByteAs(msg *bgp.BGPUpdate) error { as2Path = append(as2Path, uint16(as)) } } - as2Params = append(as2Params, bgp.NewAsPathParam(as4Param.Type, as2Path)) + as2Params = append(as2Params, bgp.NewAsPathParam(segType, as2Path)) // 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) + switch segType { + case bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SEQ, bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SET: + // pass + default: + if as4param, ok := param.(*bgp.As4PathParam); ok { + as4Params = append(as4Params, as4param) + } } } msg.PathAttributes[idx] = bgp.NewPathAttributeAsPath(as2Params) @@ -111,21 +117,20 @@ func UpdatePathAttrs4ByteAs(msg *bgp.BGPUpdate) error { asLen := 0 asConfedLen := 0 - asParams := make([]*bgp.As4PathParam, 0, len(asAttr.Value)) + asParams := make([]bgp.AsPathParamInterface, 0, len(asAttr.Value)) for _, param := range asAttr.Value { asLen += param.ASLen() - p := param.(*bgp.As4PathParam) - switch p.Type { + switch param.GetType() { case bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SET: - asConfedLen += 1 + asConfedLen++ case bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SEQ: - asConfedLen += len(p.AS) + asConfedLen += len(param.GetAS()) } - asParams = append(asParams, p) + asParams = append(asParams, param) } as4Len := 0 - as4Params := make([]*bgp.As4PathParam, 0, len(as4Attr.Value)) + as4Params := make([]bgp.AsPathParamInterface, 0, len(as4Attr.Value)) if as4Attr != nil { for _, p := range as4Attr.Value { // RFC 6793 6. Error Handling @@ -162,14 +167,14 @@ func UpdatePathAttrs4ByteAs(msg *bgp.BGPUpdate) error { keepNum := asLen + asConfedLen - as4Len - newParams := make([]*bgp.As4PathParam, 0, len(asAttr.Value)) + newParams := make([]bgp.AsPathParamInterface, 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 - newParams = append(newParams, bgp.NewAs4PathParam(param.Type, param.AS[:keepNum])) + newParams = append(newParams, bgp.NewAs4PathParam(param.GetType(), param.GetAS()[:keepNum])) keepNum = 0 } @@ -180,12 +185,15 @@ func UpdatePathAttrs4ByteAs(msg *bgp.BGPUpdate) error { 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 { - newParams[len(newParams)-1] = bgp.NewAs4PathParam(param.Type, append(lastParam.AS, param.AS[:255-len(lastParam.AS)]...)) - newParams = append(newParams, bgp.NewAs4PathParam(param.Type, param.AS[255-len(lastParam.AS):])) + lastParamAS := lastParam.GetAS() + paramType := param.GetType() + paramAS := param.GetAS() + if paramType == lastParam.GetType() && paramType == bgp.BGP_ASPATH_ATTR_TYPE_SEQ { + if len(lastParamAS)+len(paramAS) > 255 { + newParams[len(newParams)-1] = bgp.NewAs4PathParam(paramType, append(lastParamAS, paramAS[:255-len(lastParamAS)]...)) + newParams = append(newParams, bgp.NewAs4PathParam(paramType, paramAS[255-len(lastParamAS):])) } else { - newParams[len(newParams)-1] = bgp.NewAs4PathParam(param.Type, append(lastParam.AS, param.AS...)) + newParams[len(newParams)-1] = bgp.NewAs4PathParam(paramType, append(lastParamAS, paramAS...)) } } else { newParams = append(newParams, param) diff --git a/table/path.go b/table/path.go index a04e0d66..de60e615 100644 --- a/table/path.go +++ b/table/path.go @@ -196,10 +196,10 @@ func (path *Path) IsEOR() bool { func cloneAsPath(asAttr *bgp.PathAttributeAsPath) *bgp.PathAttributeAsPath { newASparams := make([]bgp.AsPathParamInterface, len(asAttr.Value)) for i, param := range asAttr.Value { - asParam := param.(*bgp.As4PathParam) - as := make([]uint32, len(asParam.AS)) - copy(as, asParam.AS) - newASparams[i] = bgp.NewAs4PathParam(asParam.Type, as) + asList := param.GetAS() + as := make([]uint32, len(asList)) + copy(as, asList) + newASparams[i] = bgp.NewAs4PathParam(param.GetType(), as) } return bgp.NewPathAttributeAsPath(newASparams) } @@ -439,11 +439,11 @@ func (path *Path) GetSourceAs() uint32 { if len(asPathParam) == 0 { return 0 } - asPath := asPathParam[len(asPathParam)-1].(*bgp.As4PathParam) - if asPath.Num == 0 { + asList := asPathParam[len(asPathParam)-1].GetAS() + if len(asList) == 0 { return 0 } - return asPath.AS[asPath.Num-1] + return asList[len(asList)-1] } return 0 } @@ -631,14 +631,15 @@ func (path *Path) GetAsPathLen() int { func (path *Path) GetAsString() string { s := bytes.NewBuffer(make([]byte, 0, 64)) if aspath := path.GetAsPath(); aspath != nil { - for i, paramIf := range aspath.Value { - segment := paramIf.(*bgp.As4PathParam) + for i, param := range aspath.Value { + segType := param.GetType() + asList := param.GetAS() if i != 0 { s.WriteString(" ") } sep := " " - switch segment.Type { + switch segType { case bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SEQ: s.WriteString("(") case bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SET: @@ -648,13 +649,13 @@ func (path *Path) GetAsString() string { s.WriteString("{") sep = "," } - for j, as := range segment.AS { + for j, as := range asList { s.WriteString(fmt.Sprintf("%d", as)) - if j != len(segment.AS)-1 { + if j != len(asList)-1 { s.WriteString(sep) } } - switch segment.Type { + switch segType { case bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SEQ: s.WriteString(")") case bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SET: @@ -668,26 +669,26 @@ func (path *Path) GetAsString() string { } func (path *Path) GetAsList() []uint32 { - return path.getAsListofSpecificType(true, true) + return path.getAsListOfSpecificType(true, true) } func (path *Path) GetAsSeqList() []uint32 { - return path.getAsListofSpecificType(true, false) + return path.getAsListOfSpecificType(true, false) } -func (path *Path) getAsListofSpecificType(getAsSeq, getAsSet bool) []uint32 { +func (path *Path) getAsListOfSpecificType(getAsSeq, getAsSet bool) []uint32 { asList := []uint32{} if aspath := path.GetAsPath(); aspath != nil { - for _, paramIf := range aspath.Value { - segment := paramIf.(*bgp.As4PathParam) - if getAsSeq && segment.Type == bgp.BGP_ASPATH_ATTR_TYPE_SEQ { - asList = append(asList, segment.AS...) + for _, param := range aspath.Value { + segType := param.GetType() + if getAsSeq && segType == bgp.BGP_ASPATH_ATTR_TYPE_SEQ { + asList = append(asList, param.GetAS()...) continue } - if getAsSet && segment.Type == bgp.BGP_ASPATH_ATTR_TYPE_SET { - asList = append(asList, segment.AS...) + if getAsSet && segType == bgp.BGP_ASPATH_ATTR_TYPE_SET { + asList = append(asList, param.GetAS()...) } else { asList = append(asList, 0) } @@ -757,7 +758,7 @@ func (path *Path) PrependAsn(asn uint32, repeat uint8, confed bool) { original := path.GetAsPath() asns := make([]uint32, repeat) - for i, _ := range asns { + for i := range asns { asns[i] = asn } @@ -769,13 +770,14 @@ func (path *Path) PrependAsn(asn uint32, repeat uint8, confed bool) { } if len(asPath.Value) > 0 { - fst := asPath.Value[0].(*bgp.As4PathParam) - if fst.Type == segType { - if len(fst.AS)+int(repeat) > 255 { - repeat = uint8(255 - len(fst.AS)) + param := asPath.Value[0] + asList := param.GetAS() + if param.GetType() == segType { + if int(repeat)+len(asList) > 255 { + repeat = uint8(255 - len(asList)) } - fst.AS = append(asns[:int(repeat)], fst.AS...) - fst.Num += repeat + newAsList := append(asns[:int(repeat)], asList...) + asPath.Value[0] = bgp.NewAs4PathParam(segType, newAsList) asns = asns[int(repeat):] } } @@ -800,9 +802,9 @@ func (path *Path) RemovePrivateAS(localAS uint32, option config.RemovePrivateAsO case config.REMOVE_PRIVATE_AS_OPTION_ALL, config.REMOVE_PRIVATE_AS_OPTION_REPLACE: newASParams := make([]bgp.AsPathParamInterface, 0, len(original.Value)) for _, param := range original.Value { - asParam := param.(*bgp.As4PathParam) - newASParam := make([]uint32, 0, len(asParam.AS)) - for _, as := range asParam.AS { + asList := param.GetAS() + newASParam := make([]uint32, 0, len(asList)) + for _, as := range asList { if isPrivateAS(as) { if option == config.REMOVE_PRIVATE_AS_OPTION_REPLACE { newASParam = append(newASParam, localAS) @@ -812,7 +814,7 @@ func (path *Path) RemovePrivateAS(localAS uint32, option config.RemovePrivateAsO } } if len(newASParam) > 0 { - newASParams = append(newASParams, bgp.NewAs4PathParam(asParam.Type, newASParam)) + newASParams = append(newASParams, bgp.NewAs4PathParam(param.GetType(), newASParam)) } } path.setPathAttr(bgp.NewPathAttributeAsPath(newASParams)) @@ -826,10 +828,10 @@ func (path *Path) removeConfedAs() { return } newAsParams := make([]bgp.AsPathParamInterface, 0, len(original.Value)) - for _, v := range original.Value { - p := v.(*bgp.As4PathParam) - if p.Type == bgp.BGP_ASPATH_ATTR_TYPE_SEQ || p.Type == bgp.BGP_ASPATH_ATTR_TYPE_SET { - newAsParams = append(newAsParams, p) + for _, param := range original.Value { + switch param.GetType() { + case bgp.BGP_ASPATH_ATTR_TYPE_SEQ, bgp.BGP_ASPATH_ATTR_TYPE_SET: + newAsParams = append(newAsParams, param) } } path.setPathAttr(bgp.NewPathAttributeAsPath(newAsParams)) @@ -843,16 +845,17 @@ func (path *Path) ReplaceAS(localAS, peerAS uint32) *Path { newASParams := make([]bgp.AsPathParamInterface, 0, len(original.Value)) changed := false for _, param := range original.Value { - asParam := param.(*bgp.As4PathParam) - newASParam := make([]uint32, 0, len(asParam.AS)) - for _, as := range asParam.AS { + segType := param.GetType() + asList := param.GetAS() + newASParam := make([]uint32, 0, len(asList)) + for _, as := range asList { if as == peerAS { as = localAS changed = true } newASParam = append(newASParam, as) } - newASParams = append(newASParams, bgp.NewAs4PathParam(asParam.Type, newASParam)) + newASParams = append(newASParams, bgp.NewAs4PathParam(segType, newASParam)) } if changed { path = path.Clone(path.IsWithdraw) |