packet/bgp: Getter functions for AS segment

This patch adds getter functions for the segment type and AS list of
each segment without using type assertion.

Signed-off-by: IWASE Yusuke <[email protected]>
This commit is contained in:
IWASE Yusuke
2018-04-03 09:16:41 +09:00
parent a25522eddd
commit 264bd0ca12
8 changed files with 119 additions and 91 deletions
+4 -4
View File
@@ -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)
+22
View File
@@ -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
+5 -12
View File
@@ -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) {
+3 -3
View File
@@ -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 {
+5 -4
View File
@@ -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
+8 -7
View File
@@ -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
+28 -20
View File
@@ -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)
+44 -41
View File
@@ -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)