Ejemplo n.º 1
0
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
}
Ejemplo n.º 2
0
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
}
Ejemplo n.º 3
0
Archivo: mrt.go Proyecto: osrg/gobgp
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
}
Ejemplo n.º 4
0
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
}