Skip to content
Snippets Groups Projects
Unverified Commit 20458529 authored by Pravein Govindan Kannan's avatar Pravein Govindan Kannan Committed by GitHub
Browse files

NETOBSERV-306 : Enable ipv6 support (#24)

* Enable ipv6 support

* Add space in union declaration

* Add source to IPv6 type

* Re-structured the ringbuffer datastructure due to bugs with union

* Correct formatting errors

* ebpf go modules for the v6 support

Co-authored-by: Pravein <Pravein Govindan Kannan>
parent 1c124c0d
Branches
Tags
No related merge requests found
......@@ -17,13 +17,21 @@ struct data_link {
} __attribute__((packed));
// L3 network layer
struct network {
// todo: add protocol
// todo: support ipv6
struct v4ip {
u32 src_ip;
u32 dst_ip;
} __attribute__((packed));
struct v6ip {
struct in6_addr src_ip6;
struct in6_addr dst_ip6;
} __attribute__((packed));
struct network {
struct v4ip v4ip;
struct v6ip v6ip;
} __attribute__((packed));
// L4 transport layer
struct transport {
u16 src_port;
......
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/in.h>
#include <linux/tcp.h>
#include <linux/udp.h>
......@@ -32,8 +33,8 @@ static inline int fill_iphdr(struct iphdr *ip, void *data_end, struct flow *flow
return DISCARD;
}
flow->network.src_ip = __bpf_ntohl(ip->saddr);
flow->network.dst_ip = __bpf_ntohl(ip->daddr);
flow->network.v4ip.src_ip = __bpf_ntohl(ip->saddr);
flow->network.v4ip.dst_ip = __bpf_ntohl(ip->daddr);
flow->transport.protocol = ip->protocol;
switch (ip->protocol) {
......@@ -57,6 +58,36 @@ static inline int fill_iphdr(struct iphdr *ip, void *data_end, struct flow *flow
return SUBMIT;
}
// sets flow fields from IPv6 header information
static inline int fill_ip6hdr(struct ipv6hdr *ip, void *data_end, struct flow *flow) {
if ((void *)ip + sizeof(*ip) > data_end) {
return DISCARD;
}
flow->network.v6ip.src_ip6 = ip->saddr;
flow->network.v6ip.dst_ip6 = ip->daddr;
flow->transport.protocol = ip->nexthdr;
switch (ip->nexthdr) {
case IPPROTO_TCP: {
struct tcphdr *tcp = (void *)ip + sizeof(*ip);
if ((void *)tcp + sizeof(*tcp) <= data_end) {
flow->transport.src_port = __bpf_ntohs(tcp->source);
flow->transport.dst_port = __bpf_ntohs(tcp->dest);
}
} break;
case IPPROTO_UDP: {
struct udphdr *udp = (void *)ip + sizeof(*ip);
if ((void *)udp + sizeof(*udp) <= data_end) {
flow->transport.src_port = __bpf_ntohs(udp->source);
flow->transport.dst_port = __bpf_ntohs(udp->dest);
}
} break;
default:
break;
}
return SUBMIT;
}
// sets flow fields from Ethernet header information
static inline int fill_ethhdr(struct ethhdr *eth, void *data_end, struct flow *flow) {
if ((void *)eth + sizeof(*eth) > data_end) {
......@@ -69,6 +100,9 @@ static inline int fill_ethhdr(struct ethhdr *eth, void *data_end, struct flow *f
if (flow->protocol == ETH_P_IP) {
struct iphdr *ip = (void *)eth + sizeof(*eth);
return fill_iphdr(ip, data_end, flow);
} else if (flow->protocol == ETH_P_IPV6) {
struct ipv6hdr *ip6 = (void *)eth + sizeof(*eth);
return fill_ip6hdr(ip6, data_end, flow);
}
return SUBMIT;
}
......@@ -110,4 +144,4 @@ static inline int egress_flow_parse(struct __sk_buff *skb) {
return flow_parse(skb, EGRESS);
}
char __license[] SEC("license") = "GPL";
\ No newline at end of file
char __license[] SEC("license") = "GPL";
......@@ -26,6 +26,8 @@ import (
"github.com/netobserv/netobserv-ebpf-agent/pkg/pbflow"
)
const ipv6 = 0x86DD
var (
port = flag.Int("listen_port", 9999, "TCP port to listen for flows")
)
......@@ -38,6 +40,12 @@ var protocolByNumber = map[uint32]string{
58: "ipv6-icmp",
}
var ipProto = map[uint32]string{
0x0800: "ipv4",
0x0806: "arp",
0x86DD: "ipv6",
}
func ipIntToNetIP(ipAsInt uint32) net.IP {
var bytes [4]byte
bytes[0] = byte(ipAsInt & 0xFF)
......@@ -63,19 +71,37 @@ func main() {
}()
for records := range receivedRecords {
for _, record := range records.Entries {
log.Printf("%v %s IP %s:%d > %s:%d: protocol:%s dir:%d bytes:%d packets:%d ends: %v\n",
record.TimeFlowStart.AsTime().Local().Format("15:04:05.000000"),
record.Interface,
ipIntToNetIP(record.Network.GetSrcAddr().GetIpv4()).String(),
record.Transport.SrcPort,
ipIntToNetIP(record.Network.GetDstAddr().GetIpv4()).String(),
record.Transport.DstPort,
protocolByNumber[record.Transport.Protocol],
record.Direction,
record.Bytes,
record.Packets,
record.TimeFlowEnd.AsTime().Local().Format("15:04:05.000000"),
)
if record.EthProtocol == ipv6 {
log.Printf("%s: %v %s IP %s:%d > %s:%d: protocol:%s dir:%d bytes:%d packets:%d ends: %v\n",
ipProto[record.EthProtocol],
record.TimeFlowStart.AsTime().Local().Format("15:04:05.000000"),
record.Interface,
net.IP(record.Network.GetSrcAddr().GetIpv6()).To16(),
record.Transport.SrcPort,
net.IP(record.Network.GetDstAddr().GetIpv6()).To16(),
record.Transport.DstPort,
protocolByNumber[record.Transport.Protocol],
record.Direction,
record.Bytes,
record.Packets,
record.TimeFlowEnd.AsTime().Local().Format("15:04:05.000000"),
)
} else {
log.Printf("%s: %v %s IP %s:%d > %s:%d: protocol:%s dir:%d bytes:%d packets:%d ends: %v\n",
ipProto[record.EthProtocol],
record.TimeFlowStart.AsTime().Local().Format("15:04:05.000000"),
record.Interface,
ipIntToNetIP(record.Network.GetSrcAddr().GetIpv4()).String(),
record.Transport.SrcPort,
ipIntToNetIP(record.Network.GetDstAddr().GetIpv4()).String(),
record.Transport.DstPort,
protocolByNumber[record.Transport.Protocol],
record.Direction,
record.Bytes,
record.Packets,
record.TimeFlowEnd.AsTime().Local().Format("15:04:05.000000"),
)
}
}
}
}
No preview for this file type
No preview for this file type
......@@ -54,7 +54,7 @@ func (g *GRPCProto) ExportFlows(input <-chan []*flow.Record) {
}
}
func flowToPB(fr *flow.Record) *pbflow.Record {
func v4FlowToPB(fr *flow.Record) *pbflow.Record {
return &pbflow.Record{
EthProtocol: uint32(fr.Protocol),
Direction: pbflow.Direction(fr.Direction),
......@@ -62,7 +62,6 @@ func flowToPB(fr *flow.Record) *pbflow.Record {
SrcMac: macToUint64(&fr.DataLink.SrcMac),
DstMac: macToUint64(&fr.DataLink.DstMac),
},
// TODO: change this when se support IPV6 addresses
Network: &pbflow.Network{
SrcAddr: &pbflow.IP{IpFamily: &pbflow.IP_Ipv4{Ipv4: uint32(fr.Network.SrcAddr)}},
DstAddr: &pbflow.IP{IpFamily: &pbflow.IP_Ipv4{Ipv4: uint32(fr.Network.DstAddr)}},
......@@ -86,6 +85,54 @@ func flowToPB(fr *flow.Record) *pbflow.Record {
}
}
func v6FlowToPB(fr *flow.Record) *pbflow.Record {
return &pbflow.Record{
EthProtocol: uint32(fr.Protocol),
Direction: pbflow.Direction(fr.Direction),
DataLink: &pbflow.DataLink{
SrcMac: macToUint64(&fr.DataLink.SrcMac),
DstMac: macToUint64(&fr.DataLink.DstMac),
},
Network: &pbflow.Network{
SrcAddr: &pbflow.IP{IpFamily: &pbflow.IP_Ipv6{Ipv6: []byte{fr.NetworkV6.SrcAddr[0],
fr.NetworkV6.SrcAddr[1], fr.NetworkV6.SrcAddr[2], fr.NetworkV6.SrcAddr[3],
fr.NetworkV6.SrcAddr[4], fr.NetworkV6.SrcAddr[5], fr.NetworkV6.SrcAddr[6],
fr.NetworkV6.SrcAddr[7], fr.NetworkV6.SrcAddr[8], fr.NetworkV6.SrcAddr[9],
fr.NetworkV6.SrcAddr[10], fr.NetworkV6.SrcAddr[11], fr.NetworkV6.SrcAddr[12],
fr.NetworkV6.SrcAddr[13], fr.NetworkV6.SrcAddr[14], fr.NetworkV6.SrcAddr[15]}}},
DstAddr: &pbflow.IP{IpFamily: &pbflow.IP_Ipv6{Ipv6: []byte{fr.NetworkV6.DstAddr[0],
fr.NetworkV6.DstAddr[1], fr.NetworkV6.DstAddr[2], fr.NetworkV6.DstAddr[3],
fr.NetworkV6.DstAddr[4], fr.NetworkV6.DstAddr[5], fr.NetworkV6.DstAddr[6],
fr.NetworkV6.DstAddr[7], fr.NetworkV6.DstAddr[8], fr.NetworkV6.DstAddr[9],
fr.NetworkV6.DstAddr[10], fr.NetworkV6.DstAddr[11], fr.NetworkV6.DstAddr[12],
fr.NetworkV6.DstAddr[13], fr.NetworkV6.DstAddr[14], fr.NetworkV6.DstAddr[15]}}},
},
Transport: &pbflow.Transport{
Protocol: uint32(fr.Transport.Protocol),
SrcPort: uint32(fr.Transport.SrcPort),
DstPort: uint32(fr.Transport.DstPort),
},
Bytes: uint64(fr.Bytes),
TimeFlowStart: &timestamppb.Timestamp{
Seconds: fr.TimeFlowStart.Unix(),
Nanos: int32(fr.TimeFlowStart.Nanosecond()),
},
TimeFlowEnd: &timestamppb.Timestamp{
Seconds: fr.TimeFlowEnd.Unix(),
Nanos: int32(fr.TimeFlowEnd.Nanosecond()),
},
Packets: uint64(fr.Packets),
Interface: fr.Interface,
}
}
func flowToPB(fr *flow.Record) *pbflow.Record {
if fr.Protocol == flow.IPv6Type {
return v6FlowToPB(fr)
}
return v4FlowToPB(fr)
}
// Mac bytes are encoded in the same order as in the array. This is, a Mac
// like 11:22:33:44:55:66 will be encoded as 0x112233445566
func macToUint64(m *flow.MacAddr) uint64 {
......
......@@ -10,13 +10,17 @@ import (
)
const MacLen = 6
const IP6Len = 16
const IPv6Type = 0x86DD
// IPv6Type value as defined in IEEE 802: https://www.iana.org/assignments/ieee-802-numbers/ieee-802-numbers.xhtml
// TODO: support IPv6
type RawIP uint32
type HumanBytes uint64
type MacAddr [MacLen]uint8
type Direction uint8
type TransportProtocol uint8
type IP6Addr [IP6Len]uint8
type DataLink struct {
SrcMac MacAddr
......@@ -28,6 +32,11 @@ type Network struct {
DstAddr RawIP
}
type NetworkV6 struct {
SrcAddr IP6Addr
DstAddr IP6Addr
}
type Transport struct {
SrcPort uint16
DstPort uint16
......@@ -40,6 +49,7 @@ type key struct {
Direction Direction
DataLink DataLink
Network Network
NetworkV6 NetworkV6
Transport Transport
// TODO: add TOS field
}
......
......@@ -18,6 +18,8 @@ func TestRecordBinaryEncoding(t *testing.T) {
0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, // data_link: u8[6] dst_mac
0x06, 0x07, 0x08, 0x09, // network: u32 src_ip
0x0a, 0x0b, 0x0c, 0x0d, // network: u32 dst_ip
0x06, 0x07, 0x08, 0x09, 0x06, 0x07, 0x08, 0x09, 0x06, 0x07, 0x08, 0x09, 0x06, 0x07, 0x08, 0x09, // network6: u8[16] src_ip
0x0a, 0x0b, 0x0c, 0x0d, 0x0a, 0x0b, 0x0c, 0x0d, 0x0a, 0x0b, 0x0c, 0x0d, 0x0a, 0x0b, 0x0c, 0x0d, // network6: u8[16] dst_ip
0x0e, 0x0f, // transport: u16 src_port
0x10, 0x11, // transport: u16 dst_port
0x12, // transport: u8protocol
......@@ -38,6 +40,10 @@ func TestRecordBinaryEncoding(t *testing.T) {
SrcAddr: 0x09080706,
DstAddr: 0x0d0c0b0a,
},
NetworkV6: NetworkV6{
SrcAddr: IP6Addr{0x06, 0x07, 0x08, 0x09, 0x06, 0x07, 0x08, 0x09, 0x06, 0x07, 0x08, 0x09, 0x06, 0x07, 0x08, 0x09},
DstAddr: IP6Addr{0x0a, 0x0b, 0x0c, 0x0d, 0x0a, 0x0b, 0x0c, 0x0d, 0x0a, 0x0b, 0x0c, 0x0d, 0x0a, 0x0b, 0x0c, 0x0d},
},
Transport: Transport{
SrcPort: 0x0f0e,
DstPort: 0x1110,
......@@ -47,4 +53,5 @@ func TestRecordBinaryEncoding(t *testing.T) {
Bytes: 0x1a19181716151413,
},
}, *fr)
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment