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 (b *BGPDump) parseBGPDump(conn redis.Conn) (int, error) { day := b.day() n := 0 f, err := os.Open(b.Path()) if err != nil { return 0, err } gzipReader, err := gzip.NewReader(f) if err != nil { return n, fmt.Errorf("couldn't create gzip reader: %v", err) } scanner := bufio.NewScanner(gzipReader) scanner.Split(mrt.SplitMrt) count := 0 indexTableCount := 0 entries: for scanner.Scan() { count++ data := scanner.Bytes() hdr := &mrt.MRTHeader{} errh := hdr.DecodeFromBytes(data[:mrt.MRT_COMMON_HEADER_LEN]) if err != nil { return 0, errh } msg, err := mrt.ParseMRTBody(hdr, data[mrt.MRT_COMMON_HEADER_LEN:]) if err != nil { log.Printf("could not parse mrt body: %v", err) continue entries } if msg.Header.Type != mrt.TABLE_DUMPv2 { return 0, fmt.Errorf("unexpected message type: %d", msg.Header.Type) } switch mtrBody := msg.Body.(type) { case *mrt.PeerIndexTable: indexTableCount++ if indexTableCount != 1 { return 0, fmt.Errorf("got >1 PeerIndexTable") } case *mrt.Rib: prefix := mtrBody.Prefix if len(mtrBody.Entries) < 0 { return 0, fmt.Errorf("no entries") } for _, entry := range mtrBody.Entries { attrs: for _, attr := range entry.PathAttributes { switch attr := attr.(type) { case *bgp.PathAttributeAsPath: if len(attr.Value) < 1 { continue attrs } if v, ok := attr.Value[0].(*bgp.As4PathParam); ok { if len(v.AS) < 0 { continue attrs } conn.Send("HSET", fmt.Sprintf("i2a:%s", prefix), day, v.AS[len(v.AS)-1]) n++ if n%10000 == 0 { err := conn.Flush() if err != nil { return 0, err } } continue entries } } } } default: return 0, fmt.Errorf("unsupported message %v %s", mtrBody, spew.Sdump(msg)) } } conn.Send("SADD", "i2a:imported_dates", day) err = conn.Flush() if err != nil { return 0, err } return n, 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 }
func injectMrt(r string, filename string, count int, skip int) 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))) } 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 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 }