Skip to content

Commit

Permalink
add meter
Browse files Browse the repository at this point in the history
Co-authored-by: Takeru Hayasaka <hayatake396@gmail.com>
Co-authored-by: Wataru Mishima <watal.i27e@gmail.com>
Co-authored-by: Yuta Fukagawa <25516089+yfskyline@users.noreply.github.com>
  • Loading branch information
4 people committed Jul 19, 2023
1 parent 5af1beb commit bf023bb
Show file tree
Hide file tree
Showing 20 changed files with 918 additions and 24 deletions.
41 changes: 41 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Copyright (c) 2023 NTT Communications Corporation
# Copyright (c) 2023 Takeru Hayasaka

GOCMD=go
BINARY_NAME=fluvia
CLANG ?= clang
CFLAGS := -O2 -g -Wall $(CFLAGS)
DIFF_FROM_BRANCH_NAME ?= origin/main

GREEN := $(shell tput -Txterm setaf 2)
YELLOW := $(shell tput -Txterm setaf 3)
WHITE := $(shell tput -Txterm setaf 7)
CYAN := $(shell tput -Txterm setaf 6)
RESET := $(shell tput -Txterm sgr0)

.PHONY: all build clean

all: go-gen build

build:
mkdir -p out/bin
$(GOCMD) build -o out/bin/$(BINARY_NAME) ./cmd/$(BINARY_NAME)/main.go

clean:
rm -fr out

go-gen: export BPF_CLANG := $(CLANG)
go-gen: export BPF_CFLAGS := $(CFLAGS)
go-gen:
go generate ./...

help:
@echo ''
@echo 'Usage:'
@echo ' ${YELLOW}make${RESET} ${GREEN}<target>${RESET}'
@echo ''
@echo 'Targets:'
@awk 'BEGIN {FS = ":.*?## "} { \
if (/^[a-zA-Z_-]+:.*?##.*$$/) {printf " ${YELLOW}%-20s${GREEN}%s${RESET}\n", $$1, $$2} \
else if (/^## .*$$/) {printf " ${CYAN}%s${RESET}\n", substr($$1,4)} \
}' $(MAKEFILE_LIST)
4 changes: 4 additions & 0 deletions cmd/fluvia/fluvia.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
ipfix:
address: 127.0.0.1
port: 4739
4 changes: 3 additions & 1 deletion cmd/fluvia/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (

type flags struct {
configFile string
ifName string
}

func main() {
Expand All @@ -31,6 +32,7 @@ func main() {
// Parse flags
f := &flags{}
flag.StringVar(&f.configFile, "f", "fluvia.yaml", "Specify a configuration file")
flag.StringVar(&f.ifName, "i", "", "Specify a configuration file")
flag.Parse()

// Read configuration file
Expand All @@ -44,5 +46,5 @@ func main() {
log.Panic(err)
}

client.New(raddr)
client.New(f.ifName, raddr)
}
12 changes: 11 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,14 @@ module github.com/nttcom/fluvia

go 1.20

require gopkg.in/yaml.v3 v3.0.1
require (
github.com/cilium/ebpf v0.11.0
github.com/google/gopacket v1.1.19
github.com/pkg/errors v0.9.1
gopkg.in/yaml.v3 v3.0.1
)

require (
golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 // indirect
golang.org/x/sys v0.10.0 // indirect
)
27 changes: 27 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,3 +1,30 @@
github.com/cilium/ebpf v0.11.0 h1:V8gS/bTCCjX9uUnkUFUpPsksM8n1lXBAvHcpiFk1X2Y=
github.com/cilium/ebpf v0.11.0/go.mod h1:WE7CZAnqOL2RouJ4f1uyNhqr2P4CCvXFIqdRDUgWsVs=
github.com/frankban/quicktest v1.14.5 h1:dfYrrRyLtiqT9GyKXgdh+k4inNeTvmGbuSgZ3lx3GhA=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8=
github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 h1:MGwJjxBy0HJshjDNfLsYO8xppfqWlA5ZT9OhtUUhTNw=
golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
Expand Down
70 changes: 70 additions & 0 deletions pkg/bpf/bpf.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// Copyright (c) 2023 NTT Communications Corporation
// Copyright (c) 2023 Takeru Hayasaka
//
// This software is released under the MIT License.
// see https://github.com/nttcom/fluvia/blob/main/LICENSE

package bpf

import (
"fmt"
"net"

"github.com/cilium/ebpf"
"github.com/pkg/errors"
)

//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -no-global-types -cc $BPF_CLANG -cflags $BPF_CFLAGS xdp ../../src/main.c -- -I../../src

type XdpProbeData struct {
H_dest [6]uint8
H_source [6]uint8
H_proto uint16
_ [2]byte
V6Srcaddr struct{ In6U struct{ U6Addr8 [16]uint8 } }
V6Dstaddr struct{ In6U struct{ U6Addr8 [16]uint8 } }
NextHdr uint8
HdrExtLen uint8
RoutingType uint8
SegmentsLeft uint8
LastEntry uint8
Flags uint8
Tag uint16
Segments [10]struct{ In6U struct{ U6Addr8 [16]uint8 } }
}

func ReadXdpObjects(ops *ebpf.CollectionOptions) (*xdpObjects, error) {
obj := &xdpObjects{}
err := loadXdpObjects(obj, ops)
if err != nil {
return nil, errors.WithStack(err)
}

// TODO: BPF log level remove hardcoding. yaml in config
if err != nil {
return nil, errors.WithStack(err)
}

return obj, nil
}

const (
XDP_ABORTED uint32 = iota
XDP_DROP
XDP_PASS
XDP_TX
XDP_REDIRECT
)

func PrintEntrys(entry XdpProbeData, count uint64) {
mac := func(mac [6]uint8) string {
return fmt.Sprintf("%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5])
}
saddr := net.IP(entry.V6Srcaddr.In6U.U6Addr8[:]).String()
daddr := net.IP(entry.V6Dstaddr.In6U.U6Addr8[:]).String()

fmt.Printf(
"H_dest: %s, H_source: %v, H_proto: %v, V6Dstaddr: %v, V6Srcaddr: %v -> count: %v\n",
mac(entry.H_dest), mac(entry.H_source), entry.H_proto, daddr, saddr, count)

}
107 changes: 107 additions & 0 deletions pkg/bpf/srv6.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package bpf

import (
"encoding/binary"
"errors"
"net"

"github.com/google/gopacket"
"github.com/google/gopacket/layers"
)

type Srv6Layer struct {
layers.BaseLayer
NextHeader uint8
HdrExtLen uint8
RoutingType uint8
SegmentsLeft uint8
LastEntry uint8
Flags uint8
Tag uint16
Segments []net.IP
}

var Srv6LayerType = gopacket.RegisterLayerType(
2001,
gopacket.LayerTypeMetadata{
Name: "Srv6LayerType",
Decoder: gopacket.DecodeFunc(decodeSrv6Layer),
},
)

func (l *Srv6Layer) LayerType() gopacket.LayerType {
return Srv6LayerType
}

func (i *Srv6Layer) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
if len(data) < 8 {
df.SetTruncated()
return errors.New("SRV6 layer less then 8 bytes for SRV6 packet")
}
i.NextHeader = data[0]
i.HdrExtLen = data[1]
i.RoutingType = data[2]
i.SegmentsLeft = data[3]
i.LastEntry = data[4]
i.Flags = data[5]
i.Tag = binary.BigEndian.Uint16(data[6:8])

for j := 0; j < int(i.HdrExtLen/2); j++ {
startBit := 8 + 16*j
endBit := 24 + 16*j
var addr []byte
for k := endBit; k >= startBit; k-- {
addr = append(addr, data[k])
}
i.Segments = append(i.Segments, addr)
}
i.BaseLayer = layers.BaseLayer{
Contents: data[:8],
Payload: data[8:],
}
return nil
}

func (i *Srv6Layer) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
l := int(i.HdrExtLen)*8 + 8
bytes, err := b.PrependBytes(l)
if err != nil {
return err
}
bytes[0] = i.NextHeader
bytes[1] = i.HdrExtLen
bytes[2] = i.RoutingType
bytes[3] = i.SegmentsLeft
bytes[4] = i.LastEntry
bytes[5] = i.Flags
binary.BigEndian.PutUint16(bytes[6:], i.Tag)

for i2, address := range i.Segments {
lsb := binary.BigEndian.Uint64(address[:8])
msb := binary.BigEndian.Uint64(address[8:])
binary.BigEndian.PutUint64(bytes[8+16*i2:], lsb)
binary.BigEndian.PutUint64(bytes[16+16*i2:], msb)
}
return nil
}

func (i *Srv6Layer) NextLayerType() gopacket.LayerType {
return gopacket.LayerTypePayload
}

// Custom decode function. We can name it whatever we want
// but it should have the same arguments and return value
// When the layer is registered we tell it to use this decode function
func decodeSrv6Layer(data []byte, p gopacket.PacketBuilder) error {
i := &Srv6Layer{}
err := i.DecodeFromBytes(data, p)
if err != nil {
return err
}
p.AddLayer(i)
next := i.NextLayerType()
if next == gopacket.LayerTypeZero {
return nil
}
return p.NextDecoder(next)
}
Loading

0 comments on commit bf023bb

Please sign in to comment.