func (d *Destination) ToNativeDestination(option ...ToNativeOption) (*table.Destination, error) { if len(d.Paths) == 0 { return nil, fmt.Errorf("no path in destination") } nlri, err := getNLRI(bgp.RouteFamily(d.Paths[0].Family), d.Paths[0].Nlri) if err != nil { return nil, err } option = append(option, ToNativeOption{ NLRI: nlri, }) paths := make([]*table.Path, 0, len(d.Paths)) for _, p := range d.Paths { path, err := p.ToNativePath(option...) if err != nil { return nil, err } paths = append(paths, path) } return table.NewDestination(nlri, paths...), nil }
func injectMrt(r string, filename string, count int, skip int, onlyBest bool) error { var resource api.Resource switch r { case CMD_GLOBAL: resource = api.Resource_GLOBAL default: return fmt.Errorf("unknown resource type: %s", r) } file, err := os.Open(filename) if err != nil { return fmt.Errorf("failed to open file: %s", err) } idx := 0 ch := make(chan *api.InjectMrtRequest, 1<<20) go func() { var peers []*mrt.Peer for { buf := make([]byte, mrt.MRT_COMMON_HEADER_LEN) _, err := file.Read(buf) if err == io.EOF { break } else if err != nil { exitWithError(fmt.Errorf("failed to read: %s", err)) } h := &mrt.MRTHeader{} err = h.DecodeFromBytes(buf) if err != nil { exitWithError(fmt.Errorf("failed to parse")) } buf = make([]byte, h.Len) _, err = file.Read(buf) if err != nil { exitWithError(fmt.Errorf("failed to read")) } msg, err := mrt.ParseMRTBody(h, buf) if err != nil { printError(fmt.Errorf("failed to parse: %s", err)) continue } if globalOpts.Debug { fmt.Println(msg) } if msg.Header.Type == mrt.TABLE_DUMPv2 { subType := mrt.MRTSubTypeTableDumpv2(msg.Header.SubType) var rf bgp.RouteFamily switch subType { case mrt.PEER_INDEX_TABLE: peers = msg.Body.(*mrt.PeerIndexTable).Peers continue case mrt.RIB_IPV4_UNICAST: rf = bgp.RF_IPv4_UC case mrt.RIB_IPV6_UNICAST: rf = bgp.RF_IPv6_UC default: exitWithError(fmt.Errorf("unsupported subType: %s", subType)) } if peers == nil { exitWithError(fmt.Errorf("not found PEER_INDEX_TABLE")) } rib := msg.Body.(*mrt.Rib) nlri := rib.Prefix paths := make([]*api.Path, 0, len(rib.Entries)) for _, e := range rib.Entries { if len(peers) < int(e.PeerIndex) { exitWithError(fmt.Errorf("invalid peer index: %d (PEER_INDEX_TABLE has only %d peers)\n", e.PeerIndex, len(peers))) } if !onlyBest { path := &api.Path{ Pattrs: make([][]byte, 0), NoImplicitWithdraw: true, SourceAsn: peers[e.PeerIndex].AS, SourceId: peers[e.PeerIndex].BgpId.String(), } if rf == bgp.RF_IPv4_UC { path.Nlri, _ = nlri.Serialize() } for _, p := range e.PathAttributes { b, err := p.Serialize() if err != nil { continue } path.Pattrs = append(path.Pattrs, b) } paths = append(paths, path) } } if onlyBest { paths = func() []*api.Path { dst := table.NewDestination(nlri) pathList := make([]*table.Path, 0, len(rib.Entries)) for _, e := range rib.Entries { p := table.NewPath(&table.PeerInfo{AS: peers[e.PeerIndex].AS, ID: peers[e.PeerIndex].BgpId}, nlri, false, e.PathAttributes, time.Unix(int64(e.OriginatedTime), 0), false) dst.AddNewPath(p) pathList = append(pathList, p) } best, _, _ := dst.Calculate([]string{table.GLOBAL_RIB_NAME}) for _, p := range pathList { if p == best[table.GLOBAL_RIB_NAME] { nb, _ := nlri.Serialize() return []*api.Path{&api.Path{ Nlri: nb, NoImplicitWithdraw: true, SourceAsn: p.GetSource().AS, SourceId: p.GetSource().ID.String(), Pattrs: func() [][]byte { attrs := make([][]byte, 0) for _, a := range p.GetPathAttrs() { if b, e := a.Serialize(); e == nil { attrs = append(attrs, b) } } return attrs }(), }} } } exitWithError(fmt.Errorf("Can't find the best %v", nlri)) return []*api.Path{} }() } if idx >= skip { ch <- &api.InjectMrtRequest{ Resource: resource, Paths: paths, } } idx += 1 if idx == count+skip { break } } } close(ch) }() stream, err := client.InjectMrt(context.Background()) if err != nil { return fmt.Errorf("failed to modpath: %s", err) } for arg := range ch { err = stream.Send(arg) if err != nil { return fmt.Errorf("failed to send: %s", err) } } _, err = stream.CloseAndRecv() if err != nil { return fmt.Errorf("failed to send: %s", err) } return nil }
func injectMrt(filename string, count int, skip int, onlyBest bool) error { file, err := os.Open(filename) if err != nil { return fmt.Errorf("failed to open file: %s", err) } idx := 0 ch := make(chan []*table.Path, 1<<20) go func() { var peers []*mrt.Peer for { buf := make([]byte, mrt.MRT_COMMON_HEADER_LEN) _, err := file.Read(buf) if err == io.EOF { break } else if err != nil { exitWithError(fmt.Errorf("failed to read: %s", err)) } h := &mrt.MRTHeader{} err = h.DecodeFromBytes(buf) if err != nil { exitWithError(fmt.Errorf("failed to parse")) } buf = make([]byte, h.Len) _, err = file.Read(buf) if err != nil { exitWithError(fmt.Errorf("failed to read")) } msg, err := mrt.ParseMRTBody(h, buf) if err != nil { printError(fmt.Errorf("failed to parse: %s", err)) continue } if globalOpts.Debug { fmt.Println(msg) } if msg.Header.Type == mrt.TABLE_DUMPv2 { subType := mrt.MRTSubTypeTableDumpv2(msg.Header.SubType) switch subType { case mrt.PEER_INDEX_TABLE: peers = msg.Body.(*mrt.PeerIndexTable).Peers continue default: exitWithError(fmt.Errorf("unsupported subType: %v", subType)) } if peers == nil { exitWithError(fmt.Errorf("not found PEER_INDEX_TABLE")) } rib := msg.Body.(*mrt.Rib) nlri := rib.Prefix paths := make([]*table.Path, 0, len(rib.Entries)) for _, e := range rib.Entries { if len(peers) < int(e.PeerIndex) { exitWithError(fmt.Errorf("invalid peer index: %d (PEER_INDEX_TABLE has only %d peers)\n", e.PeerIndex, len(peers))) } source := &table.PeerInfo{ AS: peers[e.PeerIndex].AS, ID: peers[e.PeerIndex].BgpId, } t := time.Unix(int64(e.OriginatedTime), 0) paths = append(paths, table.NewPath(source, nlri, false, e.PathAttributes, t, false)) } if onlyBest { dst := table.NewDestination(nlri) for _, p := range paths { dst.AddNewPath(p) } best, _, _ := dst.Calculate([]string{table.GLOBAL_RIB_NAME}) if best[table.GLOBAL_RIB_NAME] == nil { exitWithError(fmt.Errorf("Can't find the best %v", nlri)) } paths = []*table.Path{best[table.GLOBAL_RIB_NAME]} } if idx >= skip { ch <- paths } idx += 1 if idx == count+skip { break } } } close(ch) }() stream, err := client.AddPathByStream() if err != nil { return fmt.Errorf("failed to modpath: %s", err) } for paths := range ch { err = stream.Send(paths...) if err != nil { return fmt.Errorf("failed to send: %s", err) } } if err := stream.Close(); err != nil { return fmt.Errorf("failed to send: %s", err) } return nil }