// before: // as-path : 65000, 4000, 23456, 23456, 40001 // as4-path : {10, 20, 30} 400000, 300000, 40001 // expected result: // as-path : 65000, {10, 20, 30}, 400000, 300000, 40001 func TestAsPathAs4Trans5(t *testing.T) { as := []uint16{65000, 4000, bgp.AS_TRANS, bgp.AS_TRANS, 40001} params := []bgp.AsPathParamInterface{bgp.NewAsPathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, as)} aspath := bgp.NewPathAttributeAsPath(params) as4 := []uint32{400000, 300000, 40001} as4param1 := bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, as4) as5 := []uint32{10, 20, 30} as4param2 := bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SET, as5) param4s := []*bgp.As4PathParam{as4param2, as4param1} as4path := bgp.NewPathAttributeAs4Path(param4s) msg := bgp.NewBGPUpdateMessage(nil, []bgp.PathAttributeInterface{aspath, as4path}, nil).Body.(*bgp.BGPUpdate) UpdatePathAttrs4ByteAs(msg) assert.Equal(t, len(msg.PathAttributes), 1) assert.Equal(t, len(msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value), 3) assert.Equal(t, len(msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.As4PathParam).AS), 1) assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.As4PathParam).AS[0], uint32(65000)) assert.Equal(t, len(msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[1].(*bgp.As4PathParam).AS), 3) assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[1].(*bgp.As4PathParam).AS[0], uint32(10)) assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[1].(*bgp.As4PathParam).AS[1], uint32(20)) assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[1].(*bgp.As4PathParam).AS[2], uint32(30)) assert.Equal(t, len(msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[2].(*bgp.As4PathParam).AS), 3) assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[2].(*bgp.As4PathParam).AS[0], uint32(400000)) assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[2].(*bgp.As4PathParam).AS[1], uint32(300000)) assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[2].(*bgp.As4PathParam).AS[2], uint32(40001)) }
func TestImplicitWithdrawCalculate(t *testing.T) { origin := bgp.NewPathAttributeOrigin(0) aspathParam := []bgp.AsPathParamInterface{bgp.NewAs4PathParam(2, []uint32{65001})} aspath := bgp.NewPathAttributeAsPath(aspathParam) nexthop := bgp.NewPathAttributeNextHop("10.0.0.1") med := bgp.NewPathAttributeMultiExitDisc(0) pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med} nlri := bgp.NewIPAddrPrefix(24, "10.10.0.101") updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, []*bgp.IPAddrPrefix{nlri}) peer1 := &PeerInfo{AS: 1, Address: net.IP{1, 1, 1, 1}} path1 := ProcessMessage(updateMsg, peer1, time.Now())[0] path1.Filter("1", POLICY_DIRECTION_IMPORT) // suppose peer2 has import policy to prepend as-path action := &AsPathPrependAction{ asn: 100, repeat: 1, } path2 := action.Apply(path1.Clone(false), nil) path1.Filter("2", POLICY_DIRECTION_IMPORT) path2.Filter("1", POLICY_DIRECTION_IMPORT) path2.Filter("3", POLICY_DIRECTION_IMPORT) d := NewDestination(nlri) d.AddNewPath(path1) d.AddNewPath(path2) d.Calculate(nil) assert.Equal(t, len(d.GetKnownPathList("1")), 0) // peer "1" is the originator assert.Equal(t, len(d.GetKnownPathList("2")), 1) assert.Equal(t, d.GetKnownPathList("2")[0].GetAsString(), "100 65001") // peer "2" has modified path {100, 65001} assert.Equal(t, len(d.GetKnownPathList("3")), 1) assert.Equal(t, d.GetKnownPathList("3")[0].GetAsString(), "65001") // peer "3" has original path {65001} assert.Equal(t, len(d.knownPathList), 2) // say, we removed peer2's import policy and // peer1 advertised new path with the same prefix aspathParam = []bgp.AsPathParamInterface{bgp.NewAs4PathParam(2, []uint32{65001, 65002})} aspath = bgp.NewPathAttributeAsPath(aspathParam) pathAttributes = []bgp.PathAttributeInterface{origin, aspath, nexthop, med} updateMsg = bgp.NewBGPUpdateMessage(nil, pathAttributes, []*bgp.IPAddrPrefix{nlri}) path3 := ProcessMessage(updateMsg, peer1, time.Now())[0] path3.Filter("1", POLICY_DIRECTION_IMPORT) d.AddNewPath(path3) d.Calculate(nil) assert.Equal(t, len(d.GetKnownPathList("1")), 0) // peer "1" is the originator assert.Equal(t, len(d.GetKnownPathList("2")), 1) assert.Equal(t, d.GetKnownPathList("2")[0].GetAsString(), "65001 65002") // peer "2" has new original path {65001, 65002} assert.Equal(t, len(d.GetKnownPathList("3")), 1) assert.Equal(t, d.GetKnownPathList("3")[0].GetAsString(), "65001 65002") // peer "3" has new original path {65001, 65002} assert.Equal(t, len(d.knownPathList), 1) }
func TestMedTieBreaker(t *testing.T) { nlri := bgp.NewIPAddrPrefix(24, "10.10.0.0") p0 := func() *Path { aspath := bgp.NewPathAttributeAsPath([]bgp.AsPathParamInterface{bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{65001, 65002}), bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{65003, 65004})}) attrs := []bgp.PathAttributeInterface{aspath, bgp.NewPathAttributeMultiExitDisc(0)} return NewPath(nil, nlri, false, attrs, time.Now(), false) }() p1 := func() *Path { aspath := bgp.NewPathAttributeAsPath([]bgp.AsPathParamInterface{bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{65001, 65002}), bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{65003, 65005})}) attrs := []bgp.PathAttributeInterface{aspath, bgp.NewPathAttributeMultiExitDisc(10)} return NewPath(nil, nlri, false, attrs, time.Now(), false) }() // same AS assert.Equal(t, compareByMED(p0, p1), p0) p2 := func() *Path { aspath := bgp.NewPathAttributeAsPath([]bgp.AsPathParamInterface{bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{65003})}) attrs := []bgp.PathAttributeInterface{aspath, bgp.NewPathAttributeMultiExitDisc(10)} return NewPath(nil, nlri, false, attrs, time.Now(), false) }() // different AS assert.Equal(t, compareByMED(p0, p2), (*Path)(nil)) p3 := func() *Path { aspath := bgp.NewPathAttributeAsPath([]bgp.AsPathParamInterface{bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SEQ, []uint32{65003, 65004}), bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{65001, 65003})}) attrs := []bgp.PathAttributeInterface{aspath, bgp.NewPathAttributeMultiExitDisc(0)} return NewPath(nil, nlri, false, attrs, time.Now(), false) }() p4 := func() *Path { aspath := bgp.NewPathAttributeAsPath([]bgp.AsPathParamInterface{bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{65001, 65002}), bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SEQ, []uint32{65005, 65006})}) attrs := []bgp.PathAttributeInterface{aspath, bgp.NewPathAttributeMultiExitDisc(10)} return NewPath(nil, nlri, false, attrs, time.Now(), false) }() // ignore confed assert.Equal(t, compareByMED(p3, p4), p3) p5 := func() *Path { attrs := []bgp.PathAttributeInterface{bgp.NewPathAttributeMultiExitDisc(0)} return NewPath(nil, nlri, false, attrs, time.Now(), false) }() p6 := func() *Path { attrs := []bgp.PathAttributeInterface{bgp.NewPathAttributeMultiExitDisc(10)} return NewPath(nil, nlri, false, attrs, time.Now(), false) }() // no aspath assert.Equal(t, compareByMED(p5, p6), p5) }
//AddLocalProtoRoute is used to add local endpoint to the protocol RIB func (self *OfnetBgp) AddLocalProtoRoute(pathInfo []*OfnetProtoRouteInfo) error { if self.routerIP == "" { //ignoring populating to the bgp rib because //Bgp is not configured. return nil } log.Infof("Received AddLocalProtoRoute to add local endpoint to protocol RIB: %+v", pathInfo) // add routes attrs := []bgp.PathAttributeInterface{ bgp.NewPathAttributeOrigin(1), bgp.NewPathAttributeNextHop(pathInfo[0].nextHopIP), bgp.NewPathAttributeAsPath([]bgp.AsPathParamInterface{bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{self.myBgpAs})}), } paths := []*table.Path{} for _, path := range pathInfo { paths = append(paths, table.NewPath(nil, bgp.NewIPAddrPrefix(32, path.localEpIP), false, attrs, time.Now(), false)) } _, err := self.bgpServer.AddPath("", paths) if err != nil { return err } return nil }
// PrependAsn prepends AS number. // This function updates the AS_PATH attribute as follows. // 1) if the first path segment of the AS_PATH is of type // AS_SEQUENCE, the local system prepends the specified AS num as // the last element of the sequence (put it in the left-most // position with respect to the position of octets in the // protocol message) the specified number of times. // If the act of prepending will cause an overflow in the AS_PATH // segment (i.e., more than 255 ASes), // it SHOULD prepend a new segment of type AS_SEQUENCE // and prepend its own AS number to this new segment. // // 2) if the first path segment of the AS_PATH is of other than type // AS_SEQUENCE, the local system prepends a new path segment of type // AS_SEQUENCE to the AS_PATH, including the specified AS number in // that segment. // // 3) if the AS_PATH is empty, the local system creates a path // segment of type AS_SEQUENCE, places the specified AS number // into that segment, and places that segment into the AS_PATH. func (path *Path) PrependAsn(asn uint32, repeat uint8) { original := path.GetAsPath() asns := make([]uint32, repeat) for i, _ := range asns { asns[i] = asn } var asPath *bgp.PathAttributeAsPath if original == nil { asPath = bgp.NewPathAttributeAsPath([]bgp.AsPathParamInterface{}) } else { asPath = cloneAsPath(original) } if len(asPath.Value) > 0 { fst := asPath.Value[0].(*bgp.As4PathParam) if fst.Type == bgp.BGP_ASPATH_ATTR_TYPE_SEQ { if len(fst.AS)+int(repeat) > 255 { repeat = uint8(255 - len(fst.AS)) } fst.AS = append(asns[:int(repeat)], fst.AS...) fst.Num += repeat asns = asns[int(repeat):] } } if len(asns) > 0 { p := bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, asns) asPath.Value = append([]bgp.AsPathParamInterface{p}, asPath.Value...) } path.setPathAttr(asPath) }
func strToASParam(str string) *bgp.PathAttributeAsPath { toList := func(asstr, sep string) []uint32 { as := make([]uint32, 0) l := strings.Split(asstr, sep) for _, s := range l { v, _ := strconv.ParseUint(s, 10, 32) as = append(as, uint32(v)) } return as } var atype uint8 var as []uint32 if strings.HasPrefix(str, "{") { atype = bgp.BGP_ASPATH_ATTR_TYPE_SET as = toList(str[1:len(str)-1], ",") } else if strings.HasPrefix(str, "(") { atype = bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SET as = toList(str[1:len(str)-1], " ") } else { atype = bgp.BGP_ASPATH_ATTR_TYPE_SEQ as = toList(str, " ") } return bgp.NewPathAttributeAsPath([]bgp.AsPathParamInterface{bgp.NewAs4PathParam(atype, as)}) }
func TestTimeTieBreaker(t *testing.T) { origin := bgp.NewPathAttributeOrigin(0) aspathParam := []bgp.AsPathParamInterface{bgp.NewAs4PathParam(2, []uint32{65001})} aspath := bgp.NewPathAttributeAsPath(aspathParam) nexthop := bgp.NewPathAttributeNextHop("10.0.0.1") med := bgp.NewPathAttributeMultiExitDisc(0) pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med} nlri := bgp.NewIPAddrPrefix(24, "10.10.0.0") updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, []*bgp.IPAddrPrefix{nlri}) peer1 := &PeerInfo{AS: 2, LocalAS: 1, Address: net.IP{1, 1, 1, 1}, ID: net.IP{1, 1, 1, 1}} path1 := ProcessMessage(updateMsg, peer1, time.Now())[0] peer2 := &PeerInfo{AS: 2, LocalAS: 1, Address: net.IP{2, 2, 2, 2}, ID: net.IP{2, 2, 2, 2}} // weaker router-id path2 := ProcessMessage(updateMsg, peer2, time.Now().Add(-1*time.Hour))[0] // older than path1 d := NewDestination(nlri) d.AddNewPath(path1) d.AddNewPath(path2) d.Calculate(nil) assert.Equal(t, len(d.knownPathList), 2) assert.Equal(t, true, d.GetBestPath("").GetSource().ID.Equal(net.IP{2, 2, 2, 2})) // path from peer2 win // this option disables tie breaking by age SelectionOptions.ExternalCompareRouterId = true d = NewDestination(nlri) d.AddNewPath(path1) d.AddNewPath(path2) d.Calculate(nil) assert.Equal(t, len(d.knownPathList), 2) assert.Equal(t, true, d.GetBestPath("").GetSource().ID.Equal(net.IP{1, 1, 1, 1})) // path from peer1 win }
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) } return bgp.NewPathAttributeAsPath(newASparams) }
func TestCalculate2(t *testing.T) { origin := bgp.NewPathAttributeOrigin(0) aspathParam := []bgp.AsPathParamInterface{bgp.NewAs4PathParam(2, []uint32{65001})} aspath := bgp.NewPathAttributeAsPath(aspathParam) nexthop := bgp.NewPathAttributeNextHop("10.0.0.1") med := bgp.NewPathAttributeMultiExitDisc(0) pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med} nlri := bgp.NewIPAddrPrefix(24, "10.10.0.0") // peer1 sends normal update message 10.10.0.0/24 update1 := bgp.NewBGPUpdateMessage(nil, pathAttributes, []*bgp.IPAddrPrefix{nlri}) peer1 := &PeerInfo{AS: 1, Address: net.IP{1, 1, 1, 1}} path1 := ProcessMessage(update1, peer1, time.Now())[0] d := NewDestination(nlri) d.AddNewPath(path1) d.Calculate(nil) // suppose peer2 sends grammaatically correct but semantically flawed update message // which has a withdrawal nlri not advertised before update2 := bgp.NewBGPUpdateMessage([]*bgp.IPAddrPrefix{nlri}, pathAttributes, nil) peer2 := &PeerInfo{AS: 2, Address: net.IP{2, 2, 2, 2}} path2 := ProcessMessage(update2, peer2, time.Now())[0] assert.Equal(t, path2.IsWithdraw, true) d.AddWithdraw(path2) d.Calculate(nil) // we have a path from peer1 here assert.Equal(t, len(d.knownPathList), 1) // after that, new update with the same nlri comes from peer2 update3 := bgp.NewBGPUpdateMessage(nil, pathAttributes, []*bgp.IPAddrPrefix{nlri}) path3 := ProcessMessage(update3, peer2, time.Now())[0] assert.Equal(t, path3.IsWithdraw, false) d.AddNewPath(path3) d.Calculate(nil) // this time, we have paths from peer1 and peer2 assert.Equal(t, len(d.knownPathList), 2) // now peer3 sends normal update message 10.10.0.0/24 peer3 := &PeerInfo{AS: 3, Address: net.IP{3, 3, 3, 3}} update4 := bgp.NewBGPUpdateMessage(nil, pathAttributes, []*bgp.IPAddrPrefix{nlri}) path4 := ProcessMessage(update4, peer3, time.Now())[0] d.AddNewPath(path4) d.Calculate(nil) // we must have paths from peer1, peer2 and peer3 assert.Equal(t, len(d.knownPathList), 3) }
func TestBMP(t *testing.T) { aspath1 := []bgp.AsPathParamInterface{ bgp.NewAs4PathParam(2, []uint32{1000000}), bgp.NewAs4PathParam(1, []uint32{1000001, 1002}), bgp.NewAs4PathParam(2, []uint32{1003, 100004}), } mp_nlri := []bgp.AddrPrefixInterface{bgp.NewIPv6AddrPrefix(100, "fe80:1234:1234:5667:8967:af12:8912:1023")} p := []bgp.PathAttributeInterface{ bgp.NewPathAttributeOrigin(3), bgp.NewPathAttributeAsPath(aspath1), bgp.NewPathAttributeMpUnreachNLRI(mp_nlri), } w := []*bgp.IPAddrPrefix{} n := []*bgp.IPAddrPrefix{} msg := bgp.NewBGPUpdateMessage(w, p, n) pList := ProcessMessage(msg, peerR1(), time.Now()) CreateUpdateMsgFromPaths(pList) }
// before: // as-path : 65000, 4000, 40000, 30000, 40001 // expected result: // as-path : 65000, 4000, 40000, 30000, 40001 func TestAsPathAs2Trans2(t *testing.T) { as := []uint32{65000, 4000, 40000, 30000, 40001} params := []bgp.AsPathParamInterface{bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, as)} aspath := bgp.NewPathAttributeAsPath(params) msg := bgp.NewBGPUpdateMessage(nil, []bgp.PathAttributeInterface{aspath}, nil).Body.(*bgp.BGPUpdate) UpdatePathAttrs2ByteAs(msg) assert.Equal(t, len(msg.PathAttributes), 1) assert.Equal(t, len(msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value), 1) assert.Equal(t, len(msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.AsPathParam).AS), 5) assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.AsPathParam).AS[0], uint16(65000)) assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.AsPathParam).AS[1], uint16(4000)) assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.AsPathParam).AS[2], uint16(40000)) assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.AsPathParam).AS[3], uint16(30000)) assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.AsPathParam).AS[4], uint16(40001)) }
//DeleteLocalProtoRoute withdraws local endpoints from protocol RIB func (self *OfnetBgp) DeleteLocalProtoRoute(pathInfo []*OfnetProtoRouteInfo) error { log.Infof("Received DeleteLocalProtoRoute to withdraw local endpoint to protocol RIB: %v", pathInfo) attrs := []bgp.PathAttributeInterface{ bgp.NewPathAttributeOrigin(1), bgp.NewPathAttributeNextHop(pathInfo[0].nextHopIP), bgp.NewPathAttributeAsPath([]bgp.AsPathParamInterface{bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{self.myBgpAs})}), } paths := []*table.Path{} for _, path := range pathInfo { paths = append(paths, table.NewPath(nil, bgp.NewIPAddrPrefix(32, path.localEpIP), true, attrs, time.Now(), false)) } if err := self.bgpServer.DeletePath(nil, bgp.RF_IPv4_UC, "", paths); err != nil { return err } return nil }
//DeleteLocalProtoRoute withdraws local endpoints from protocol RIB func (self *OfnetBgp) DeleteLocalProtoRoute(pathInfo *OfnetProtoRouteInfo) error { log.Infof("Received DeleteLocalProtoRoute to withdraw local endpoint to protocol RIB: %v", pathInfo) path := &api.Path{ Pattrs: make([][]byte, 0), } //form appropraite path attributes for path to be withdrawn nlri := bgp.NewIPAddrPrefix(32, pathInfo.localEpIP) path.Nlri, _ = nlri.Serialize() origin, _ := bgp.NewPathAttributeOrigin(bgp.BGP_ORIGIN_ATTR_TYPE_EGP).Serialize() path.Pattrs = append(path.Pattrs, origin) aspathParam := []bgp.AsPathParamInterface{bgp.NewAs4PathParam(2, []uint32{self.myBgpAs})} aspath, _ := bgp.NewPathAttributeAsPath(aspathParam).Serialize() path.Pattrs = append(path.Pattrs, aspath) n, _ := bgp.NewPathAttributeNextHop(pathInfo.nextHopIP).Serialize() path.Pattrs = append(path.Pattrs, n) path.IsWithdraw = true //paths := []*api.Path{path} arg := &api.DeletePathRequest{ Resource: api.Resource_GLOBAL, Path: path, } //send arguement stream client := api.NewGobgpApiClient(self.cc) if client == nil { log.Errorf("Gobgpapi stream invalid") return nil } _, err := client.DeletePath(context.Background(), arg) if err != nil { log.Errorf("Fail to enforce Modpathi: %v", err) return err } return nil }
func TestCalculate(t *testing.T) { origin := bgp.NewPathAttributeOrigin(0) aspathParam := []bgp.AsPathParamInterface{bgp.NewAs4PathParam(2, []uint32{65001})} aspath := bgp.NewPathAttributeAsPath(aspathParam) nexthop := bgp.NewPathAttributeNextHop("10.0.0.1") med := bgp.NewPathAttributeMultiExitDisc(0) pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med} nlri := bgp.NewIPAddrPrefix(24, "10.10.0.101") updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, []*bgp.IPAddrPrefix{nlri}) peer1 := &PeerInfo{AS: 1, Address: net.IP{1, 1, 1, 1}} path1 := ProcessMessage(updateMsg, peer1, time.Now())[0] path1.Filter("1", POLICY_DIRECTION_IMPORT) action := &AsPathPrependAction{ asn: 100, repeat: 10, } path2 := action.Apply(path1.Clone(false), nil) path1.Filter("2", POLICY_DIRECTION_IMPORT) path2.Filter("1", POLICY_DIRECTION_IMPORT) d := NewDestination(nlri) d.AddNewPath(path1) d.AddNewPath(path2) d.Calculate([]string{"1", "2"}) assert.Equal(t, len(d.GetKnownPathList("1")), 0) assert.Equal(t, len(d.GetKnownPathList("2")), 1) assert.Equal(t, len(d.knownPathList), 2) d.AddWithdraw(path1.Clone(true)) d.Calculate([]string{"1", "2"}) assert.Equal(t, len(d.GetKnownPathList("1")), 0) assert.Equal(t, len(d.GetKnownPathList("2")), 0) assert.Equal(t, len(d.knownPathList), 0) }
//AddLocalProtoRoute is used to add local endpoint to the protocol RIB func (self *OfnetBgp) AddLocalProtoRoute(pathInfo *OfnetProtoRouteInfo) error { log.Infof("Received AddLocalProtoRoute to add local endpoint to protocol RIB: %v", pathInfo) if self.routerIP == "" { //ignoring populating to the bgp rib because //Bgp is not configured. return nil } path := &api.Path{ Pattrs: make([][]byte, 0), SourceAsn: self.myBgpAs, } aspathParam := []bgp.AsPathParamInterface{bgp.NewAs4PathParam(2, []uint32{self.myBgpAs})} aspath, _ := bgp.NewPathAttributeAsPath(aspathParam).Serialize() path.Pattrs = append(path.Pattrs, aspath) // form the path structure with appropriate path attributes nlri := bgp.NewIPAddrPrefix(32, pathInfo.localEpIP) path.Nlri, _ = nlri.Serialize() origin, _ := bgp.NewPathAttributeOrigin(bgp.BGP_ORIGIN_ATTR_TYPE_EGP).Serialize() path.Pattrs = append(path.Pattrs, origin) log.Infof("Received AddLocalProtoRoute aspath: %v", aspath) mpls, err := bgp.ParseMPLSLabelStack("3") if err != nil { return nil } var nlri2 bgp.AddrPrefixInterface nlri2 = bgp.NewLabeledIPAddrPrefix(32, pathInfo.localEpIP, *mpls) mpreach, _ := bgp.NewPathAttributeMpReachNLRI(pathInfo.nextHopIP, []bgp.AddrPrefixInterface{nlri2}).Serialize() log.Infof("Received AddLocalProtoRoute nlri2: %v, mpreach: %v", nlri2, mpreach) path.Pattrs = append(path.Pattrs, mpreach) //path.Pattrs = append(path.Pattrs, n) arg := &api.AddPathRequest{ Resource: api.Resource_GLOBAL, VrfId: "default", Path: path, } log.Infof("BGP - arg %v ", arg) // add routes /* prefix := pathInfo.localEpIP log.Infof("BGP - Prefix %v " , prefix ) path2, err := cmd.ParsePath(bgp.RF_IPv4_MPLS, []string{"10.200.1.25/32", "3"}) log.Infof("BGP - Path2 %v " , path2 ) log.Infof("BGP - Err %v " , err ) req := bgpserver.NewGrpcRequest(bgpserver.REQ_ADD_PATH, "", bgp.RouteFamily(0), &api.AddPathRequest{ Resource: api.Resource_GLOBAL, Path: path2, }) self.bgpServer.GrpcReqCh <- req res := <-req.ResponseCh if err := res.Err(); err != nil { log.Fatal(err) log.Infof("BGP - Err %v " , err) } */ //send arguement stream client := api.NewGobgpApiClient(self.cc) if client == nil { log.Infof("Gobgpapi stream invalid") return nil } stream, err := client.AddPath(context.Background(), arg) if err != nil { log.Infof("Fail to enforce Modpath: %v %v", err, stream) return err } return nil }
// Test adding/deleting Vlrouter routes func TestOfnetBgpVlrouteAddDelete(t *testing.T) { neighborAs := "500" peer := "50.1.1.3" routerIP := "50.1.1.2/24" as := "65002" //Add Bgp neighbor and check if it is successful for i := 0; i < NUM_VLRTR_AGENT; i++ { err := vlrtrAgents[i].AddBgp(routerIP, as, neighborAs, peer) time.Sleep(5 * time.Second) if err != nil { t.Errorf("Error adding Bgp Neighbor: %v", err) return } attrs := []bgp.PathAttributeInterface{ bgp.NewPathAttributeOrigin(1), bgp.NewPathAttributeNextHop("50.1.1.3"), bgp.NewPathAttributeAsPath([]bgp.AsPathParamInterface{bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{65002})}), } path := table.NewPath(nil, bgp.NewIPAddrPrefix(32, "20.20.20.20"), false, attrs, time.Now(), false) vlrtrAgents[i].protopath.ModifyProtoRib(path) log.Infof("Adding path to the Bgp Rib") time.Sleep(2 * time.Second) // verify flow entry exists brName := "vlrtrBridge" + fmt.Sprintf("%d", i) flowList, err := ofctlFlowDump(brName) if err != nil { t.Errorf("Error getting flow entries. Err: %v", err) } ipFlowMatch := fmt.Sprintf("priority=100,ip,nw_dst=20.20.20.20") ipTableId := IP_TBL_ID if !ofctlFlowMatch(flowList, ipTableId, ipFlowMatch) { t.Errorf("Could not find the route %s on ovs %s", ipFlowMatch, brName) return } log.Infof("Found ipflow %s on ovs %s", ipFlowMatch, brName) // withdraw the route path.IsWithdraw = true vlrtrAgents[i].protopath.ModifyProtoRib(path) log.Infof("Withdrawing route from BGP rib") // verify flow entry exists brName = "vlrtrBridge" + fmt.Sprintf("%d", i) flowList, err = ofctlFlowDump(brName) if err != nil { t.Errorf("Error getting flow entries. Err: %v", err) } ipFlowMatch = fmt.Sprintf("priority=100,ip,nw_dst=20.20.20.20") ipTableId = IP_TBL_ID if ofctlFlowMatch(flowList, ipTableId, ipFlowMatch) { t.Errorf("Found the route %s on ovs %s which was withdrawn", ipFlowMatch, brName) return } log.Infof("ipflow %s on ovs %s has been deleted from OVS", ipFlowMatch, brName) } }
func UpdatePathAttrs4ByteAs(msg *bgp.BGPUpdate) error { var asAttr *bgp.PathAttributeAsPath var as4Attr *bgp.PathAttributeAs4Path asAttrPos := 0 as4AttrPos := 0 for i, attr := range msg.PathAttributes { switch attr.(type) { case *bgp.PathAttributeAsPath: asAttr = attr.(*bgp.PathAttributeAsPath) 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) } } if as4Attr != nil { msg.PathAttributes = append(msg.PathAttributes[:as4AttrPos], msg.PathAttributes[as4AttrPos+1:]...) } if asAttr == nil || as4Attr == nil { return nil } 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 { // 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) } } 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 } 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 { lastParam.AS = append(lastParam.AS, param.AS...) } } else { newParams = append(newParams, param) } } newIntfParams := make([]bgp.AsPathParamInterface, 0, len(asAttr.Value)) for _, p := range newParams { newIntfParams = append(newIntfParams, p) } msg.PathAttributes[asAttrPos] = bgp.NewPathAttributeAsPath(newIntfParams) return nil }
func TestMultipath(t *testing.T) { UseMultiplePaths.Enabled = true origin := bgp.NewPathAttributeOrigin(0) aspathParam := []bgp.AsPathParamInterface{bgp.NewAs4PathParam(2, []uint32{65000})} aspath := bgp.NewPathAttributeAsPath(aspathParam) nexthop := bgp.NewPathAttributeNextHop("192.168.150.1") med := bgp.NewPathAttributeMultiExitDisc(100) pathAttributes := []bgp.PathAttributeInterface{ origin, aspath, nexthop, med, } nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.10.0")} updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) peer1 := &PeerInfo{AS: 1, Address: net.IP{1, 1, 1, 1}, ID: net.IP{1, 1, 1, 1}} path1 := ProcessMessage(updateMsg, peer1, time.Now())[0] peer2 := &PeerInfo{AS: 2, Address: net.IP{2, 2, 2, 2}, ID: net.IP{2, 2, 2, 2}} med = bgp.NewPathAttributeMultiExitDisc(100) nexthop = bgp.NewPathAttributeNextHop("192.168.150.2") pathAttributes = []bgp.PathAttributeInterface{ origin, aspath, nexthop, med, } updateMsg = bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) path2 := ProcessMessage(updateMsg, peer2, time.Now())[0] d := NewDestination(nlri[0]) d.AddNewPath(path1) d.AddNewPath(path2) best, w, multi := d.Calculate([]string{GLOBAL_RIB_NAME}) assert.Equal(t, len(best), 1) assert.Equal(t, len(w), 0) assert.Equal(t, len(multi), 2) assert.Equal(t, len(d.GetKnownPathList(GLOBAL_RIB_NAME)), 2) path3 := path2.Clone(true) d.AddWithdraw(path3) best, w, multi = d.Calculate([]string{GLOBAL_RIB_NAME}) assert.Equal(t, len(best), 1) assert.Equal(t, len(w), 1) assert.Equal(t, len(multi), 1) assert.Equal(t, len(d.GetKnownPathList(GLOBAL_RIB_NAME)), 1) peer3 := &PeerInfo{AS: 3, Address: net.IP{3, 3, 3, 3}, ID: net.IP{3, 3, 3, 3}} med = bgp.NewPathAttributeMultiExitDisc(50) nexthop = bgp.NewPathAttributeNextHop("192.168.150.3") pathAttributes = []bgp.PathAttributeInterface{ origin, aspath, nexthop, med, } updateMsg = bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) path4 := ProcessMessage(updateMsg, peer3, time.Now())[0] d.AddNewPath(path4) best, w, multi = d.Calculate([]string{GLOBAL_RIB_NAME}) assert.Equal(t, len(best), 1) assert.Equal(t, len(w), 0) assert.Equal(t, len(multi), 1) assert.Equal(t, len(d.GetKnownPathList(GLOBAL_RIB_NAME)), 2) nexthop = bgp.NewPathAttributeNextHop("192.168.150.2") pathAttributes = []bgp.PathAttributeInterface{ origin, aspath, nexthop, med, } updateMsg = bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) path5 := ProcessMessage(updateMsg, peer2, time.Now())[0] d.AddNewPath(path5) best, w, multi = d.Calculate([]string{GLOBAL_RIB_NAME}) assert.Equal(t, len(best), 1) assert.Equal(t, len(w), 0) assert.Equal(t, len(multi), 2) assert.Equal(t, len(d.GetKnownPathList(GLOBAL_RIB_NAME)), 3) UseMultiplePaths.Enabled = false }