From 45b4757d2be2b41b2258ca8b0c9b4dd1b72b28aa Mon Sep 17 00:00:00 2001 From: shach33 <45016480+shach33@users.noreply.github.com> Date: Wed, 18 Jan 2023 13:07:35 +0530 Subject: [PATCH] Added TCP Flags to Flow Record metrics (#68) * Test commit * Adding TCP flags * Adding TCP flags to record metrics.TODO: Remove log stmts * Updated tcp flags u32-> u16 * Updated indentation in C file * Update flow.h * Indent fixed. Tab -> 4 space fixing indents Indent fixes for flows.c Indent fixes for flows.c-II Still fixing indents * Removed extra file * Added clang-format config to bpf/. To use clang-format -i <file.c> * Fixed message record member sequences * Added TCP Flags combinations Read from flw Updated changes according to comments on PR * Removed log statements. Rebase merges * Fixing merge conflits * Revert the renaming of grpc_test file * Simplify setting flags for v4,v6 * Add flags to ipfix exporter * Update protobuf * Remove type conversions due to conflicts * Remove .gitignore change * Fix indentation * Remove commented line * Fixed typecast errors since move to go 1.18 * Reverting commit d1e9c44. Added changes as separate PR * set flags for v6 Co-authored-by: Pravein Govindan Kannan <pravein.govindan.kannan@ibm.com> --- bpf/.clang-format | 9 ++ bpf/flow.h | 2 + bpf/flows.c | 72 +++++++--- .../server/flowlogs-dump-collector.go | 8 +- go.mod | 2 +- pkg/ebpf/bpf_bpfeb.o | Bin 17424 -> 20504 bytes pkg/ebpf/bpf_bpfel.o | Bin 17520 -> 21032 bytes pkg/exporter/ipfix.go | 126 +++++++++--------- pkg/exporter/kafka_proto_test.go | 4 +- pkg/exporter/proto.go | 4 +- pkg/flow/account_test.go | 24 ++-- pkg/flow/deduper_test.go | 8 +- pkg/flow/record.go | 5 +- pkg/flow/record_test.go | 3 + pkg/flow/tracer_map_test.go | 20 +-- pkg/grpc/grpc_test.go | 9 +- pkg/pbflow/flow.pb.go | 105 ++++++++------- pkg/pbflow/flow_grpc.pb.go | 2 +- proto/flow.proto | 1 + 19 files changed, 238 insertions(+), 166 deletions(-) create mode 100644 bpf/.clang-format diff --git a/bpf/.clang-format b/bpf/.clang-format new file mode 100644 index 00000000..92af251e --- /dev/null +++ b/bpf/.clang-format @@ -0,0 +1,9 @@ +{ + BasedOnStyle: LLVM, + AllowShortFunctionsOnASingleLine: InlineOnly, + ColumnLimit: 100, + IndentWidth: 4, + SortIncludes: false, + ReflowComments: false, + TabWidth: 4, +} diff --git a/bpf/flow.h b/bpf/flow.h index 1248838b..af668b5e 100644 --- a/bpf/flow.h +++ b/bpf/flow.h @@ -17,6 +17,8 @@ typedef struct flow_metrics_t { // as output from bpf_ktime_get_ns() u64 start_mono_time_ts; u64 end_mono_time_ts; + // TCP Flags from https://www.ietf.org/rfc/rfc793.txt + u16 flags; // The positive errno of a failed map insertion that caused a flow // to be sent via ringbuffer. // 0 otherwise diff --git a/bpf/flows.c b/bpf/flows.c index 790f24b8..72fa02ae 100644 --- a/bpf/flows.c +++ b/bpf/flows.c @@ -26,7 +26,6 @@ #include <linux/udp.h> #include <linux/tcp.h> #include <string.h> - #include <stdbool.h> #include <linux/if_ether.h> @@ -42,6 +41,20 @@ #define INGRESS 0 #define EGRESS 1 +// Flags according to RFC 9293 & https://www.iana.org/assignments/ipfix/ipfix.xhtml +#define FIN_FLAG 0x01 +#define SYN_FLAG 0x02 +#define RST_FLAG 0x04 +#define PSH_FLAG 0x08 +#define ACK_FLAG 0x10 +#define URG_FLAG 0x20 +#define ECE_FLAG 0x40 +#define CWR_FLAG 0x80 +// Custom flags exported +#define SYN_ACK_FLAG 0x100 +#define FIN_ACK_FLAG 0x200 +#define RST_ACK_FLAG 0x400 + // Common Ringbuffer as a conduit for ingress/egress flows to userspace struct { __uint(type, BPF_MAP_TYPE_RINGBUF); @@ -62,8 +75,35 @@ volatile const u8 trace_messages = 0; const u8 ip4in6[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff}; +// sets the TCP header flags for connection information +static inline void set_flags(struct tcphdr *th, u16 *flags) { + //If both ACK and SYN are set, then it is server -> client communication during 3-way handshake. + if (th->ack && th->syn) { + *flags |= SYN_ACK_FLAG; + } else if (th->ack && th->fin ) { + // If both ACK and FIN are set, then it is graceful termination from server. + *flags |= FIN_ACK_FLAG; + } else if (th->ack && th->rst ) { + // If both ACK and RST are set, then it is abrupt connection termination. + *flags |= RST_ACK_FLAG; + } else if (th->fin) { + *flags |= FIN_FLAG; + } else if (th->syn) { + *flags |= SYN_FLAG; + } else if (th->rst) { + *flags |= RST_FLAG; + } else if (th->psh) { + *flags |= PSH_FLAG; + } else if (th->urg) { + *flags |= URG_FLAG; + } else if (th->ece) { + *flags |= ECE_FLAG; + } else if (th->cwr) { + *flags |= CWR_FLAG; + } +} // sets flow fields from IPv4 header information -static inline int fill_iphdr(struct iphdr *ip, void *data_end, flow_id *id) { +static inline int fill_iphdr(struct iphdr *ip, void *data_end, flow_id *id, u16 *flags) { if ((void *)ip + sizeof(*ip) > data_end) { return DISCARD; } @@ -81,6 +121,7 @@ static inline int fill_iphdr(struct iphdr *ip, void *data_end, flow_id *id) { if ((void *)tcp + sizeof(*tcp) <= data_end) { id->src_port = __bpf_ntohs(tcp->source); id->dst_port = __bpf_ntohs(tcp->dest); + set_flags(tcp, flags); } } break; case IPPROTO_UDP: { @@ -97,7 +138,7 @@ static inline int fill_iphdr(struct iphdr *ip, void *data_end, flow_id *id) { } // sets flow fields from IPv6 header information -static inline int fill_ip6hdr(struct ipv6hdr *ip, void *data_end, flow_id *id) { +static inline int fill_ip6hdr(struct ipv6hdr *ip, void *data_end, flow_id *id, u16 *flags) { if ((void *)ip + sizeof(*ip) > data_end) { return DISCARD; } @@ -113,6 +154,7 @@ static inline int fill_ip6hdr(struct ipv6hdr *ip, void *data_end, flow_id *id) { if ((void *)tcp + sizeof(*tcp) <= data_end) { id->src_port = __bpf_ntohs(tcp->source); id->dst_port = __bpf_ntohs(tcp->dest); + set_flags(tcp, flags); } } break; case IPPROTO_UDP: { @@ -128,7 +170,7 @@ static inline int fill_ip6hdr(struct ipv6hdr *ip, void *data_end, flow_id *id) { return SUBMIT; } // sets flow fields from Ethernet header information -static inline int fill_ethhdr(struct ethhdr *eth, void *data_end, flow_id *id) { +static inline int fill_ethhdr(struct ethhdr *eth, void *data_end, flow_id *id, u16 *flags) { if ((void *)eth + sizeof(*eth) > data_end) { return DISCARD; } @@ -138,15 +180,15 @@ static inline int fill_ethhdr(struct ethhdr *eth, void *data_end, flow_id *id) { if (id->eth_protocol == ETH_P_IP) { struct iphdr *ip = (void *)eth + sizeof(*eth); - return fill_iphdr(ip, data_end, id); + return fill_iphdr(ip, data_end, id, flags); } else if (id->eth_protocol == ETH_P_IPV6) { struct ipv6hdr *ip6 = (void *)eth + sizeof(*eth); - return fill_ip6hdr(ip6, data_end, id); + return fill_ip6hdr(ip6, data_end, id, flags); } else { // TODO : Need to implement other specific ethertypes if needed // For now other parts of flow id remain zero - memset (&(id->src_ip),0, sizeof(struct in6_addr)); - memset (&(id->dst_ip),0, sizeof(struct in6_addr)); + memset(&(id->src_ip), 0, sizeof(struct in6_addr)); + memset(&(id->dst_ip), 0, sizeof(struct in6_addr)); id->transport_protocol = 0; id->src_port = 0; id->dst_port = 0; @@ -154,7 +196,6 @@ static inline int fill_ethhdr(struct ethhdr *eth, void *data_end, flow_id *id) { return SUBMIT; } - static inline int flow_monitor(struct __sk_buff *skb, u8 direction) { // If sampling is defined, will only parse 1 out of "sampling" flows if (sampling != 0 && (bpf_get_prandom_u32() % sampling) != 0) { @@ -166,7 +207,8 @@ static inline int flow_monitor(struct __sk_buff *skb, u8 direction) { flow_id id; u64 current_time = bpf_ktime_get_ns(); struct ethhdr *eth = data; - if (fill_ethhdr(eth, data_end, &id) == DISCARD) { + u16 flags = 0; + if (fill_ethhdr(eth, data_end, &id, &flags) == DISCARD) { return TC_ACT_OK; } id.if_index = skb->ifindex; @@ -184,7 +226,7 @@ static inline int flow_monitor(struct __sk_buff *skb, u8 direction) { if (aggregate_flow->start_mono_time_ts == 0) { aggregate_flow->start_mono_time_ts = current_time; } - + aggregate_flow->flags |= flags; long ret = bpf_map_update_elem(&aggregated_flows, &id, aggregate_flow, BPF_ANY); if (trace_messages && ret != 0) { // usually error -16 (-EBUSY) is printed here. @@ -198,9 +240,10 @@ static inline int flow_monitor(struct __sk_buff *skb, u8 direction) { // Key does not exist in the map, and will need to create a new entry. flow_metrics new_flow = { .packets = 1, - .bytes=skb->len, + .bytes = skb->len, .start_mono_time_ts = current_time, .end_mono_time_ts = current_time, + .flags = flags, }; // even if we know that the entry is new, another CPU might be concurrently inserting a flow @@ -230,15 +273,14 @@ static inline int flow_monitor(struct __sk_buff *skb, u8 direction) { } } return TC_ACT_OK; - } SEC("tc_ingress") -int ingress_flow_parse (struct __sk_buff *skb) { +int ingress_flow_parse(struct __sk_buff *skb) { return flow_monitor(skb, INGRESS); } SEC("tc_egress") -int egress_flow_parse (struct __sk_buff *skb) { +int egress_flow_parse(struct __sk_buff *skb) { return flow_monitor(skb, EGRESS); } char _license[] SEC("license") = "GPL"; diff --git a/examples/flowlogs-dump/server/flowlogs-dump-collector.go b/examples/flowlogs-dump/server/flowlogs-dump-collector.go index 26aff7fc..3d2c8ab9 100644 --- a/examples/flowlogs-dump/server/flowlogs-dump-collector.go +++ b/examples/flowlogs-dump/server/flowlogs-dump-collector.go @@ -61,7 +61,7 @@ func main() { log.SetFlags(0) flag.Parse() - receivedRecords := make(chan *pbflow.Records, 100) + receivedRecords := make(chan *pbflow.Records, 1000) log.Println("starting flowlogs-dump-collector on port", *port) go func() { _, err := grpc.StartCollector(*port, receivedRecords) @@ -72,7 +72,7 @@ func main() { for records := range receivedRecords { for _, record := range records.Entries { 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", + log.Printf("%s: %v %s IP %s:%d > %s:%d: protocol:%s dir:%d bytes:%d packets:%d flags:%d ends: %v\n", ipProto[record.EthProtocol], record.TimeFlowStart.AsTime().Local().Format("15:04:05.000000"), record.Interface, @@ -84,10 +84,11 @@ func main() { record.Direction, record.Bytes, record.Packets, + record.Flags, 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", + log.Printf("%s: %v %s IP %s:%d > %s:%d: protocol:%s dir:%d bytes:%d packets:%d flags:%d ends: %v\n", ipProto[record.EthProtocol], record.TimeFlowStart.AsTime().Local().Format("15:04:05.000000"), record.Interface, @@ -99,6 +100,7 @@ func main() { record.Direction, record.Bytes, record.Packets, + record.Flags, record.TimeFlowEnd.AsTime().Local().Format("15:04:05.000000"), ) } diff --git a/go.mod b/go.mod index 4df6d82a..b06f7bfd 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ require ( github.com/caarlos0/env/v6 v6.9.1 github.com/cilium/ebpf v0.8.1 github.com/gavv/monotime v0.0.0-20190418164738-30dba4353424 + github.com/golang/protobuf v1.5.2 github.com/mariomac/guara v0.0.0-20220523124851-5fc279816f1f github.com/netobserv/gopipes v0.3.0 github.com/paulbellamy/ratecounter v0.2.0 @@ -35,7 +36,6 @@ require ( github.com/go-openapi/jsonreference v0.19.5 // indirect github.com/go-openapi/swag v0.19.14 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/protobuf v1.5.2 // indirect github.com/google/gnostic v0.5.7-v3refs // indirect github.com/google/go-cmp v0.5.7 // indirect github.com/google/gofuzz v1.1.0 // indirect diff --git a/pkg/ebpf/bpf_bpfeb.o b/pkg/ebpf/bpf_bpfeb.o index ee6465770f750f986efe7ab54426cac2f1b26477..8f980bfe43902ca98206d83f9e1c41e70ad28c29 100644 GIT binary patch literal 20504 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 Zs-eX@NC^mox~U)<-adxz@`I;e2>{ZQq1ONa delta 6587 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 SG?yKylL^Z3lP5d)NB{t?xbN!# diff --git a/pkg/ebpf/bpf_bpfel.o b/pkg/ebpf/bpf_bpfel.o index b28228617135f0ee03e3b7426a289ba71b98b12f..300e3452ad3b4b963cdf91ba9e7550ec1b03328e 100644 GIT binary patch literal 21032 zcmb<-^>JfjWMqH=MuzVU2p&w7f#HQOg6#liIxq+_Ff#1d1albni$iD$HV6$P6B8jU zQASQMqm_Yyft`VY0VbZ#z`&ruz`#%rrS~&|l`+^0L1=v_Ee}$}z`zj7pv?@DNh}Kh zQ4EO{K42PTE-M2A!~RAvmw}y;fq{>Kfk8J>6|BCn5hTmNP%L%rKS)JkBMXRPD3-bk z<%5+m6iZ!!@*xf>mbwh(Lqerk>JpR>*3M8YbrH(v01FgLorUrt{w<a|2jxQordaAU zln)98kbBNR`CL%_=b?OVDE|V4-^2sv7dG;O>2yX029S;ZieN6oerPz|VPaqqU|?X# z);a;!C(78u&~}%BA(T;q5u_eDe3Zc9!wB~H{wWZ1s<{?`^=)TlU;r_Sr5=GOhGMCQ zQ2G;;{s^YGL%hjQJnI3NUp(tRl)eY0??UN2Q2I8Mz6GUkLg^b&`Z|<;2c_Ra={HdN zHI#k@rC&nn7f|{+l>Pvv--GGIMk%ldVc}HH#K0iIz`#(f^$aYJEDj34Vy&lO@nWgR zV7eR{-o;W+!2HBUIUMGF1IuHY_Z2K&EcF>oBh32(<`*_XGEniXUtoUmte;T&2bBH} zp{0I<X;H@0OoE{Nz{tu7N?FM9Y6gy1CUAnyYy`zJ14jBN)`FOKhmnB+l%GNFu>ggK z6vV#FMimtQ!O~T+7Q|hc`XKJ!4$3x+3=El#dSLyabZWrBz;K+AfdNGC7X}M6go9F@ z5CelKvmOJ35Ca2P9}@!uio765UW<W25aIrCkoimu4BMF*z~$6-1_&Jr@h$_153*su zD2QZW2nS_*5vchr3=E>Ij0_A=J}7|Te2{xU<p;7pMh1p*R%kv8hL{)14AKQL59Abo zs6J$IP{{)FA4p{=GbCf8_=|;sA(WXPY#_+r;CzW3E*v0vNd5=OgNi;B{R$v?NcjPh z2gM(XyaPxc;xLeW0|NsCET5(_?q~S_|Nnnjxy{P37witq^iv1&9s_#0P}rynR$nXy z$v1`2bW$t@$uEVC%20VoJ}HEzKUh90Y=jh8uyUoa5#&2iIS46V3LE92`XS{>AvB*A zOF_z&!bVxBJfwUnY?OiWA>~YAqcoHcDQ^m)`My{RQtlKsN<!r!<xgQFs1yL%4=IP> z`A`Z{9u+o<LDfUbrNTxXC?8TT6*lTZ`H=Feuu%)jhm=!=joMH?r2Hyu)PV9K<yK)M zqyjCLf|O^4jcQPNNI6#6s1D^r%D2Ks6DS{2o)k8kLivz#r?Alo%7>IQg^k8gKCGMp z<wB5uA?0^rqajotQmz+5^KG#dq}(iQ)Q8GL%G1I|5ilQ?o`^569HHe^J_CAr<pnOU za=_+hHiAkoM1Dt<JA}$BQ0awDAF<_?6WIRI@@lY^SDN7Rij^S~T<@WmM?|N?S&;lu zJPVR<if2LcL-8y~J}I6BN&m&OAo-$r79_nF&w}KG;#rXVT|5ht?~7+a@^kSlNIox~ z1<Aj~vmp7pcornT7SDp@<KkJ6^0Igqq?|0C1t}kkXF=K*#j~L8tXYt9koxT@NV_4i z5L*6todSnvveX|iy?+rn`7^LHF)*C?|Np-PsPcjcfk{yN8YCpjFcZu#g!UOg`2|#e z6@qIE1_oGrw2%o>|D-cP>d!)Ehys5|@x%ZU2eq^OA<2!QkQvgDOlO9w2e(!k82q92 zVj&}>K7`xH0%<S%JA$3VP{<0Z=ouK&q4jkk3#b-mVDNW^%CkV~%XAi~`D~z4h=IXB z1tJd;2fHT(%4dYMqx~VpBRE_@{@)L&-WbZ6A@aor5Pu<ygKCsw1Bm~NA=MiLsJ#ga zr(y+=DGUrCe}JUm?q`Fx>)D|0V}i8z{UOx>Lm?BSy#NX~kU53SpxzAw11vlXnL({V z1_pTev4DKTz~Ju;@lRq2gyx5aSLJd@JAXe^yqtxB0aSukd(8l+hhhgvJ&G(3syV8? zCP3w(?P(<app;eZ)d7`<)U(L?LH@1wYJkdvLWzN4e+9%{<s8uVcmt#zjI0mjlVS%* zJ-ojZsva88#Q~58TX6xTUIK*=NWFg&MBRRfHimLGNc*!m0g`Tz#X<fqPJpB@WO0yt zixWVh&A@;x4)SMl0wld6i-YVfPJpB<WO0yBixVK}uUG(*E<x>WkjcdYkaSzf2+0VA zY>)(>4owICQ1^rQAoKkp)guFl4{{$YeT1?>(o5w+X#5F4%&A-mjV}R+`IQTy@go39 zFO>_S@gV>*oq?ga0g}#&9U$qexBy~qaR4NJ7BWKGU!e30a(^Kcr2PfU_x=+h;a)5N z5l8qFqK{BHvmcUe7`8)#i2+pZfN~gmc~l5-K7%NuCOAWhGH8HlkUFRo*dd_yFDU$B z=7P)v#Skll5?DQ`p9^9nORWH>%fv#kHipW@(EI@{uR!@16yC{N2f*r*wRS*gt36P9 z3xt+h1E#ZQ9RbrI^FbyiOKkx2i=~c%Y4mW|zZj&7fq|Wwfnf!f@)tck_JcgZz`!8N z#tCvh1IXVH6Cflad?4uyBoAq6LgYc=0!mu@lOcRqxU@sfEzW|t6QmEK0z!iHg@gJN z(0BsrYX<d086f!qT|L4bU%&={<n6&M2mvw=)Pe<>1G1Wx;XPQQav`K2irkL|=Til9 zuspIjs9Y*mfMg70ad19W0GW<x7sBGPSOL<GMph3>C&dbo_A;_KC}$KaKoUZ+0LV55 z21L4sR1lR5A?*cZeGvCT+Rw=1AQOreApK)xafo{%{Rw1oP`WEtfb=_%#Ubv6^e>Rb zA?}6tLj*vkBD)uo3Mv;u+9$~RAnt|qH;~04?uArD$l@TAixnXKL1b}=dr`*^K;aH? zFQfuRRu6G6WSpW{0Hhn)y^#K5<w8h*5Lq9@y^#JQvN*)OnBy}L_d?4dNO1_Rmq9ib zD?rLCWOE?yh1P>e>LKoh)PKbSAXUijh17eM3nBeSWb+{Ih1PFK=0V&G%8jV$6yjb; z{f2A~#J!OE4p|)Jl41o&xsNOkaWBNeVrV&!NWYNMvT`A0oDo?c#J!OE09hR3UP%3b zEDmumq@F+)hqxC~k06Uf+zYLDA<hHG2gJRQdb(HuRLdZTFQlBQTnHK8L^coNUPwKQ zEDmumsC2;=zL4?}Sv|zPkO~M{9O7O`!G|mkaWANrVqho+aX{nQu<=3xaPiDgxDZmF z77K)d%dg6XkopGM9EkfNr6aO9#Qk<)eaPaF@V3Pehq&JcLmc9MYYcIalZzFsz~aRM zAXgxVw<TD-av`MtLbe~IvRJ_#ERQS>ajzSOIK;h>205~Nh<jZy)I;10X}}_@hqxEg zUoRE_jea4!7t+A3TnMS3k@Z2`>yKd%#JzqP;t=;jCO(kOfw&hk?|>{0aj!RqIS}`P zMma#~!vidj$bX(-e&Rw%y8_cZ$iO4AIK;dlu)bme$UF$byg;yc=0ZsOqgVjap+U%p zg5~!^k|ku^m4N}=&T3&`V3-P)MV&_h)g-!!7XLs}l#VB}GC=b?(mV|)W$PyDK+Q+3 z$7wzO!^$8Fwinb60r{_0fB`(-02@b!g$GC;6lA#ML3)w!|Np5)MfpVvr3ER8C7F5Y z3TZj{<qE1PTnrHL#FP{i(d7KnoRmEE5{07F;?$zDRE6S##N<?k%shpXj8ui9%)IoZ z(lk8<m!kZF0+>by_W(#5M6wqrbN*{a@O%eI!3lN-1`rkmB_xml0|U6X4)PypI2}~- zDL{tRL9*Zi4^+B=#6h(oq{L)k1o1(60i=k5fq@B9!h(4ydO&7^M41>Ez`asX4GFc2 z0aQza%md|OP^VBiCl;4pcRxsaLwWC8<<xgdRDQ3eKZZyC}uWZ(eRK%i2Ti-Ca! zl;=S?3{qP$Fn~&5P>l!jdIAG@DgYcV8BjJTcNT!!)eH;_psp!sUJ_IT|6pKXr~^3; zB+kgd&<<sHFfuSqU;s~1Fw9_NU;s7aL4I1m$iT1$;y4aa4Y~o!2HCp}!e#`8DTsd* z!sh^0fhVABP%VBI!Um7DKx#p-05}XlegK6(D9mp|0vH^&PZ$^&AT0^7T2O$og6w$3 zz`y`$c`z`1W?*0d#Q{jgUj_ySNQ(%>17ooHAh&?b2k8aPr7|!ufc*hh!2mKA(q9Lu z0lAG25@8&m^dSmmgIZM55H@;R0ows;L4ovxFr@d!0M-w+g9((jbRhaUK&?PaMh4K> zF$<{0=fTJTPCFpA0gMa`pw=TueHfGtirY*mdjSIjLltyB_yGe0LjxluzCJK8FtkC< z2enGOplndfbpnJ99)$v>O^`jz3=AxwG9DCmkX8r-!(v7TaES&|vz(EE0pvE&e9Kyh zem+p^7{UaZz`z8mQ}!`}=e${VFfcHjU}Rtbg&9cp43rJ>$5kjBWbQ2}8|0@KP&UYp zk5D$qfB&HD1EBeJCWx6JzY0Owpvf|6C>t~cr43~}FfuS0L)i(83=B3*3=E(i0w|2^ zq2dZm3=A$%wgVFbgFlp=z{J210%bQaF)+kJ*$bE$7*e6^156AIIZ*ZkCI)c(4(wlM z28Ko^1_n@`S72sf=z+2qFf%YrgQ{0xVPIGUWjnAiFsy~L6F>=ufq?<k^J!p#%*BD? z?*Iz}!#=1Q237`!<50E&w4ea>tQ=Sw7%o7?8=&G0(DV#)7szOYFeIJB#6fbPcw%H= zU<IZ5n@kK0kX{)`6pWc5wLiG<1gm+>#J~XQ>4D`z1QV>(W@KRC1(gBMm>3v9y{=bG zV0}E09wP$-6Pi4%>~aR@9tIvr&l9W%#T+Akuow@dCkwKYfeTWrg4vv)@~H$=C^0bb zfqKVC>5~i6+JmSAl`*wYb)a$-Ssh3YtO^=-pjIU)d_b-I9;hBr3lyYhGK3E+$3Q|L ztzch(>VA+u5S{^1#|J9AVTu?S7`Q-cKpJ521Zv@d)PwTkLZ}`{YY?gm>L!>vP<glw zst(f1#I6n$7H6UAAgxyhh9~^scmRun;vA$CR3<`t!;muY6+gIK0;_@6K@1@GL0Z({ zxL|;^(is>);R9;Xg2E5veo$)|l;1#Z1hu3=eh0bZ6C@77W`fE9ki8%?e}P57OK2E4 zKn{T{r(s~o%qwAtk9Q0Ta*T`*_Kb3k4~YzLjgMz2sVqok$W5$>Pt7YS%1kY0NXaZp zO)iNCHAspXKxBMo3XF~~VMr~>h%YG0FUe2N&w;AV%+F&eE=rEiO-yD;DJ}uiAbw^6 zn44JumMzFHDgpDsjFO_nykZawVOVBbd}dxsY6U~7p&3JbJcumKE6z;MOHENI&H(8y zwE&4*Fu;YAGZKp!GV{#h6H`(kj8cYD2+sn>Ff@a)jExxL<C9XsrYEI>d8Nii2-848 z1QGyyIybeXC^H!v0#HtT2}40*a&~G-F+);iNop}eaY<rPNqla8UVeN@W^QVHNijoe zUJ9x}T25kmF{oLWm(NgYW&-konF+$uocz3W1rWiIom$CImY7qT%8;0zUX+@iSdy9o zjfVL6;_UdO(zG;&oYXvqg6xubXtWh&GZdDlmZrw%CW0G&4DhHa%Sp_OF90<c^GX=N zoRZ{B2m`E!p`a);zbLb$k|8rMy(qP~I6gBC68tc_BpDhX$w>?uiNzTVCCTy0If=!^ znJEk@i6x0(B0e=Qg&{AoAQPNQ5_2<iDjAAWbMs45<1-6P7;^HH6LY{UxS$za&<v&$ zln$VxU?#})_}tWzM23>$lEmBshVsm!)Oe8B(~I-ti&N8!8NiIps#HkI%ucN=W+={P zD9%oTdj}kg1&Kw)sUU|#J;|V_uLnj+1!?*q6~%hV3<?Sg3Pq_UrA2w*W;iJNGE4G{ zG>Ws6bQC=O+=E<$gEg%oHs$8$f#ewUN>VFIK=EIanXHhRmy?+XYK@nm8BkJGnp~m) zk39t~u#u$}3Xn{enV+YrPz|;}GfhFGI5D>%2h@63v{f)rP*YRTNGeE+Pfsn0FDOdP zOUciTFEuvO&{R-WfT`3}04ar;QI?;XqM!v1ywtoD1zQCTh=`^JD1B)bXD8{}!DOw$ zwnF4VVz^a9RF;~VC?uB_6{Y5tfRnm{tpdn#+2CXka$;Vwh9*QQ$SW|LQ%f=wv=xdo zt5WmRG_+DnGBg$J6hQWY(hbbr@$pHenK>nydGWcaxyc2U8ks4&cF=-EM<KN&L)R`N zJ|(rdL`T6j#3SC($JGyN6;_>~q9->o8LqQ9zqBYh6+<t`66C^6!B!zY9^|LIlKhNf z4XCx?yaKfi<S|TLwqQpE#Crz7`~y-43xLc5B>!g?5bb@CCo&84iXnxWjzVUENoJmz z4lF1kTurFMum%Gt04Xy8)eQ)LKrPo%P|GaPwJQddy+{s&ijd$oTqdVrm<$$ynGA{w z%xXlzRsrNHaJ(hw=RlJrG(mw%7X@1d1B58ZkEo)><(VbP844Q6rodtrR8k<vZb>q7 z^p+$SXe!v)Vx(`7E)dR4(X~Ue4>`4!B!fZ{oKT^03eo_=AWfjCggO#K6DVImwSZg( z$}EY=*`U$`#4N6amoT*osX4`|3Ro1SW#%cse280BQE>?_RRzTvIP{kmrQ?uEO-{uj zlU!Z|lL2`i6k?eL&}aoGHbm@!0tPMzP8<k1oJk`uwW1^=r3j)DIkuq^Fv~%qpPQOn zoLZux1}~B_3p8~U4B*MV7*fK+njnazsRwJ#DA+213tnig3b8daMGsyBDA*!u1BfiB zUIJBrp!SD?7Q8V4ZVN!m-Q2{2_?-Ow?9zhx)ST2@4K=tbXp;eyIa83*1za9tilVK8 zU#O1{vR6@6=-NSBIttph3WgAOfdT|w6}TM)QUms6PHG-PDJZ3(E5~dwDcIU77~pdU zdV@;A7NsIW*oVz|*zCih9o?zmcAG+ttpb>Vum)6@f|?6RF##UMOT`xxItr-9>nJz{ zxWzmAMM9$p<aSVal@ui=r^e@|78fU`rxt^9aZzdsN+l0c3BsV7s-P${uOwST2{L8~ zb_J;U07^d!swpvfN;)8iB3S{Ffv2pz)N)8-u!XikK*oZw9wbts2{$J-PY2vs07;SQ zc{P|_xcrUFmzZIKoK!$A0%6RsKpj8D5)vS7Fh}X778T{?E7&UN7NwRTA{wLw9AHJM z$@xVo3R+Ma((-|hxyFN9*hOWj8fuUX4Gz&_c=>>&A5?B2MFq%okna>BregCJNE$Uk zU{eJ$2sr@A87fvna~Q-;x^|hMR%B)hYM8(zp`9WHTLoA^qN)Qq3KmMmrAfJ&B^nT| zItm7w)(o}qL<RCEti4p4f?T7PrjT8umZp$Vqk=U-Yt&RouLvB2@NNV|5bScCJqA}; zhXK|~XF!ca21xsf0o-|w&&f<q%`1lXW1zhYz4-X}__W*-lr9HMP|py%un~h^Zel?( zgI-ZSsDaG@GZ+*NU{8QMNg!TvesVTwyZ|)j4;o7Zu|caHK-h+pfuR68cnKQM_zM|x z0x1En&kumEs|N{yRy?>s#vwpl29SQxkON2$Xxs`U$id9OAj8bSz!Sp)-gg4yv&OJ6 zfXwOxDFO{1Gcz!Rfku2}nBnT?Ff%Z4sxUKv#zaB-Kzwl(X0SV8d}$SC@VYb@-&lni zyk7yv2g!qGz+iks6=nv|_&tmdG9NUK58^*yW?;}XU}gY~or3s6EDQ{)Cd>>SQ1{ue zFfd3sFoVbQLGqwAfucK@7(nBzFh1uFCWaMI^)px)7+8-mF>rw9dYKs*E`j(bm>4pk zd_GnN28lCF;CTU%eh^>m3=;!rZUDpwjYV=^VPe<-RiDAiz#y`Qk>LOmpK}c(!viRP zIx7PM>mEji4^aM15dQ!p0|#i0B{Ks9Og;k2hsm#i@}=28?qy{70p*v1_$L?{JV0wM znHd<)voSCzonZvW8_0dX*ccdut}rqrK;;G485o2vFftTC`5^T&XBZhOpnNrU1_ss} zj0_!6z7snGgX9xNh8akF-Y1L<pfO&M`4#L83^Fem8FoPBL42tfj0^{m_#pWcNPLj| z4JdytNdFr~h7U-5sW*%aKalt`Zx|UsgK;4HK<YvA5}-Ap%nS?<*cljjT^Jb*kobZw zj0^!#{y%mG1_>WV22ebM^s9i@C`K?cc!1U(GBYrEaWF6l)G#tcpz%TR2vVN{l5b&T zsDR4D_#IGw9Z0^1kzocJe*=_110+9%k>LcC4>DK8f{Eb<5}(t8iQxm3zlno^LCk}R z;R9&xATtBQIS}86iQxk~0|UrCuQ(VOlmbAJ58;F3H-d=)w8R1=502juCI$r#h&)KW zOaK#u29z(t$-uxG!^B_#<%8olgNeZdiO-wC#1H`GgW^*rhlwEri7%DI#88052gz3; z@j>z(P(CQWWD1xV79jDZ3YZvHAn`%+8<6-Q`4dn+EPfv#@j>y+zzOjmEPg$pd|3Sc zfbwDS%fSUv593Qf`LOuZK;v6L`LOu)K;wg!pn}317QY=(d3{a>2F^cB3>&y1_GNK0 zFi1o&Gwgu!yEqvbgkqQ(4nX-JdBF%~h6_+Ww5Vmc0p+jYWMELqVP^OM<%9giS-{Nj z1Im};Vqj1#VP^2)f!OE3#lRq6!OZXi%7@8Y@S@6lK>68R3=Faz%nU1_e2{+i3TB24 zNPLia2cY~#Tnr3aHOveX_#o!N^e=$&LHa@JJ@`@OJCOLi9n1_9p#0lh3=9T6%nTo( zd?{`Q2Kgz>3>E?q{jl(GfbyNV85l%nFf(L8`Lnqh7<lI}Gc+LaW#%w5On~x_g5<X_ zGn|0(|8X-gC>~*ExB%rV@Gvk)pJ8Tr0OiBvBLpG#+w(9mh`eEDXn^u3^Dr>*eqd(k zfbv)KFfa&murMq@<FA17&w}K6SQsuq`JjnyISCeq8%TT^2^NM2P`)-V1B0>*3j=5( z8I-;{c^Mc46<8QROMgN9CA<s_qADy58bT2F!T1JH{wa{W1`9(3l&{3cz#wJ8!k{4z zQE$)3z#wnK!mvXU!cXU8VBmFNVYmS0PvT=>U<_bkxB=x);bUNsWMN`>fyC!!VPg0I z<)7kXV36TpV&IU1m<QrZaWF9mAn`%+5=eZIyats2AEcj$iNONO2iw=d#NdI%=j~u( z2!QfI=F9XjF=Qa|rFxhc3Xu39`3fXHNWKHg2irG+iD3ei4@+O5HWG4s$d8|afu{h` z9s==M3qZ3sFdf)wX3&fu7Aa;>1%@VG3tAX~r2YhGGM#~eAs;+(#sprwfULzHDh`S( zWO2yyG$wEzgDk!js=fee@dZd;A1V%tV-O#P%b?<*vI`~#qCx9@K{IGOkS0|@;-K~8 zAaPLL3gW}CKhzx1TrNxuM1$t6LFzA{1tVw<A0*CzW<F&8orysLO&qk21Ee05W<ch` z@D-@N8EF1Bhl+#h2$)(B4Qlg&%z?F~L1G{b+7}BFZ-BP3L1G|W2Q_B{ns_`^`~;df zXucj~&H+$^8)N_!yF=B3$~>qLm;%iuGBR+0w#vf!AjVv%dQcex;=}M(M$o(@2Y9X@ zBnFy)1kvG8^`J5U#D`(fIth^Zp!rFVm??;0U|;~PSpc~clqaA<aEh4$v^oXOg)^AJ zJJ;b{Fk>MDXd5sha$)_JF7VnKP)`M{44xA}bE|?3T;RS0NCxD85S<5A4>Jku9nk(l zus9-eVZpiuY%ju{FndAkQ3M${;K>R!ZwoU27}y*{WWnr#nFq2Dv=#+a2ZPju_@K23 zpgIVd52}M;eDHb`r~x4LAUA;O5STnjKd8=t@j>cAbp(tLQV*&FV0_S;6Hu8C<Ac<L z%6J$bq#hQcpb!DsiO%-`Ey7{|H=P+k=7k{fLGH<c@<ClXkbgmKJ&^ezKFGcnBze%< zh6zY~ko|Me_$$!(2cUdV_=5U}uyqz7KB%k(tt|lA2jYX=4_i|K;)B-UfY!>u<U#5| zeL`eDsLu!EgY?e;aiIPM@j-n&kPyf`5FfNw2bm9Drv*-rAo&|0NhJL*(D;yY2NIqj z^^o!d!H1NS2tFwNfsBCJZvoPTWIky96S8~+nmniviY#A&CJ$P-hAa<SyN1kPfu?>3 z8XvT730eIOG<ncEC1m*@X!4*wE3&)<D3Xx;r-8<|K;wI$@j-oFWb-o6<SWql9ccU+ zXnatg8QHuYX!0k}_&3n_FVOg)J~y&?p!OItUjmeIko}Lww?N~A`s~R1BhchC(D<M} zI<k6DA03$w>Z2p`SD@(!_0f^#L49&$KB!NQ%zuHVAJivDmgfK^Y$X4J`sB#+8ffws zXnYSeegqmn1C3vS#_vGm!`dMrVNg<C0b(GzZwDIx1RDPa8vg|v{|6eM1KKVD34`o| zwNqex4K#TRG(Kny0y(@uV-U!E&{zR7A2bGm%m<A@AoD?E5Xk%$X!gO{Z!q_P#w3u{ zgT^F~`7hA)|3Kq&K&xDsd9ZVXV0;ZUc?&eY2O2*Djh}(WuR!B>pz&v*@mHYnccAf4 zpz&{@@n4|vf1vR>km@&Z{G;(T(D)W;eB}BWq(1^pJ_C&ptDj-v+kqxO1C0->k74R} zpvi;Qk0ZzT4K(=|X#5{&d=6-X17^Mi8Xq*~gls-&%n6wf8goMCN1*8kjX5F9gT|PU z`Jgc-WIkvt2AK~UV?yTdKr<gS#)K??15N$~8vh3xp99*2g!><juYtz5K;y&uBQX6D zX!5Xr2}mB)9)k5pV0>)@9X%s`T`3tk2EC%x9LRDfFv}^#O%Js82|TBOK4F1835L0h z4Wu8usti1}0yelLIUYKv0-3!)n<_!JgaJOEqL-6XmJ43<SDcxSZNV4BNbp=-JY?<$ zKF^|8TvAk$n8cu0T$u}|q0=QGx9K^BxH0%RIT^+qT0&?u3kYorrH!Gq5sWs6$Qzo& zW_7^Y&CDRe#!%YK6v8)!(uPpl%mgBC0;LU&A$%hUWeTNDjBri)Kx{LFDu>cWIA(~T z(&h$G<xtuLw7&_IRw=>fVT*6k41q0XegZ0lkmS&~;C>WH3|b7rRl?S`!p1LP642}d z<AS@xpd=1c50mf!E%IexV1Vwg0QUz$O)r>!Xt#<1wCf9-{jd!OpgsxAOb`vz4`PEb zXk9lp`+q>~huH(7L3s?OAH)agkAv*dz~~WcfEJfS&%OhxgJGC{7(a@E0W@q4p8JA{ zfoKls!e^L0AQ}|LF#RAtNZoy?{h+V`@nP5lYCrTC2beIpUjyfW&hLWihc@frQhT8K zL4Jk{Le(PkLHlb!;g7EW08~GykB6)t=6;yiYb<7h<X%Aae}rvr0SQ9eZBQnddX6Lf zB%t93+QS1<2nsLI4mFtlAU;SOwCoz>eh?cO-+?Z&p8!f6ND}Db0WuS$1U>z(fZ87b zl4O9KDFWKRgl_+2Q2z7zpAXu;f@BTD4^YAcEs{qT#1dB5!Q+K!iWnFe3ZM(qVeNO2 NA3=L<VD`htRRHZWu_yol delta 6569 zcmZ3ngz-ZM;{**U0|y2;fG`~x1Q`Sv_G?UZDyZMU1d^=oTJRr4CsqW2D2BvJA28j@ zz`(%Dz`(Gd4a{ZOKM_K+GcqvnF)%RbHm(5cFPsQc#lTQ3bq#Dz;Y1d&!eXhbP(Cx1 ze+9}1Yhx&`m%0oUV1z2T1m%Od48>9xp?nUoK(W+WD4!F`KL_PQTv#l18p>yf%AbMq zxuE>>P(C-9FH|gb0U|Jo2P{xHaq=cc10_3#wz~`rp^Uu@AbXL$tpxUV3)5r~Cf$07 zqZx{&9)Jxgmbwq6??LIiQ2Gv(z73^sLFt=N`UaG~4yE5g>9<h&4U~QjrC)*R`eLb< zU`Daj3n={@N`HXT@4<B9Bq^}(_A7%ahH_>G1_=fRhGMH{V0mP50kHT}uz0c7V=!IL z!~hP6Vy!1&e&QrKkU{kf$QmIAegi8&7Ka%46)aw?^%+bf4EzG-7fuof8OTs9^$W}| zmih^$e?aN)5L)Xum=<NKVGv}fXJ80rn!x~ydgLfF14q$Ruz{=$RbU!Z-W{9-3n!|A z<%^{tAyGI{1<HqnK;cA4kQGZod|o&almI{}{qcX0{S1W@6`>j)fn8QOQ31+-2<6K| z`H(bHI1wCl46w9PI8hcV4@onH6J?-$NZKi!C=KO9(oo?<NK_U}-Tq$>k|~@h38EN^ zr67r_a3UxoKrVzNuEL41poJu|!ii!~^^n9?I8g`6ha|SbiMmieBoP)))PnLMiLY>? zHkALS9_m94r~o7}7EaWJ@*%0TaH1NN4@sPb6V;)7NTMyAXaeO!(n#S%Qz##jmI@~t zLHUrhQ#jEW%CCneo{0uffsarJ8AAD=pnN?jACemiC+b7_kX%wYQ3TB24o(pa48>Z| zM5qN#gj&!<s0B@gQqV+L&uGCQ$N(xQJTMZW7dR2Rf(>S603}HVhVAh30%`%SR4xVa zd9f5EM2e*#9xaxFgg~(r#AEfvQV<^(OF?{6ECumlu@ofkilrcNS}cXV0Kr{;KypK| z6eJhGQh%`&q&z5=0w?x*hGHp5DyM!42nk|V21xEe&c2}JsM`q21uP5<nG+{JVm8-; z=2}(;NU@Hr+zuQOpxO$g+HCS;W;3RV7L%n}Oob8)At|?V5v2Mn)|&i_+k$bzWMiJA zy!$J_amTPfoq>U2@>iZIlB~R7k#tr_VOYonsWSXkCokf4uWtcMGVnV>==~)Sx}1f9 z!GeK-q1p>-hXW)(Bg=!5Z?)G9aAGZX0Qro80a+g8%4)9(P<cpphdHmDgMk55;?x&6 zK=S?mN~p!0&@z4kB>(R(gNm~;Fo28X1V}l6Y!RrkD|QeCD=aR6<cf4Ah<g7ZurR}Z zh%`evD+2?_;l%;qs<j?P0_5Z30BB?&X#lyjH~?e~1B!Z(4~qjJbvm*IV21{P3V2lY zAg>k&K<jt`P-A0q8NYNrt1#G&uo&`(+6>}@O!9{mEDRt%$R+-evY#Q872?v$h0r(> zfS6Oc5E>@}LSS<%7eeDe0F>()7>XM}rZO-TPv8g33l}Fq(phl<Bxw{o@J`Ma2<KD= zXM9lxrOBrS^ciI){}zz--k${4!vLxZL5@k*IslH~WUU<#I%^M<-U6Ye)_`ePA(AY$ z0n9I!Ix@Lf(4UEwak7t)+~h}s7K}$GOAARdhE6sWGG+WQIa^4b@%84(Lf2V1k3e(? zglsMrPi30?LsDTfhx8k+E9?vmARNKB`JePACRSDk1{T@LTjk6ZLH>Nez`)P|_5cG1 zs4{GUvOyJP*JMd~b;*T{4B(6hYF;j7WMBZ*cnu5;467$c%1hVpVPs%XVqjo7z`($8 zjFEu>lKvSOPC?lq&tHbJK_=XQvJ)5>7@k4dAk*GM*$WsL82&)nATwE+AZCKxDF9_N zFfuSmLfG{T3XBX4nh*|y10w^2A(WlK$iQI5#J~Wmu0S5Ng^DXMF)%nm*$zw$48Bly z0uuv65R~1(#J~^@WiMc2U`U3t4=^z>WI@>vm>3vJnXDnMV_;@rsApne0F_<}%nS@& zQ1$|528Jn64GJs_3?RcmA>_aU3cs}q;*wjL7#Kj|et?C6VGmR#s8xP+@?8aS#dA=R z237`!>r4y`pp?3Rm4V?gOxNVU3iga|Cfh11Gk%+#sHn{OlZk-=R0IE=+^Z;V1mlG< zFo5f_Fi1<C2U3MHfC7>iR4>BRRq{^0rl`cUn|JarMKz`)ypxrbjD#*jN=7~#2CxQ( zTfCFgl+>8+^G@zlGU9vzm35l@QAwH&RO<ZYo%~8kO-KZiTlm}{Ie|f&Z?clI5|bg{ zWH;p?HA_CQVc@I<N*5qSpq%aq(FM-@{(PJFDYr1Hr4|+C<ujC;nJ~o1gUFoxymSRH zQJPnrnVy%LqL7(avN=oDoKd8txFj*RAikusAeAAb9KzeYKy3-j<T{;p0R;^;jm#8X zyOiRR_{;)LoynrQijxzJ%r=|pZeg4(r2m4^cJp8Tc&5p}jPBRZf6WLkd_hhFHDW;6 zhK+%t08(Os+sp#YU~hnwfXmBdBtEEN)6I*J2k8eDDIh(dKnH1(W@cc}XJ%mF*}@Di zw_$wNEzI={Aj9H7su&m;KoXgt*sEZID_qaaz`)tS!~iN^LGmEJcmosIAuzsl0~5H0 zg7J+Tm>59e4da94LES<a->`v+p#W@OJp%*CK#&EX3<^^4nVEq>vxkYH1FV37L6wDp zL3IKX!vrYbpM`-zVh$4nC=-L!SFtcKhzc+<Y=Fvx_?!Yv3_GCw)hrAQtTIdt5}*vv z%)syz#8+Tqr~vWnnHd-qSs554RG1i6fCQj?F%>3;4N!hCD+2?k4im!xD8HJOfkA|a zk>LUopOc4?;Q^GtiWOubBf|$M{|$(*z{tP>%4f_B3^4f!CI*IjkPl!AKs{j)UyqG} zfmMZ(;RjSh2Z*o1$l$>YiK0hr3=B#-j0^!#J})~1gOCX$Ljshq4B{IwG891hAoVgj zj0_b}z9l;Y1FHoiLkBZMJvh!o*%=rlT^Jc=Kox-aye^CkE1-O^kEbv)>_FmkPGMv? z0OfbHGcbrPVPpW6FCY&r2k}=hG8|xqIQTF-1B22UMurPeKG?xq7#SY0)<YD4UA%#j z;R93wNQ2B8Mus0y{#%fXcQ7(=utC&=94L8&kwF59&wGTC!2rtV;9y|j3}IqOV27x8 z=3rouOkiXvK;rWzFfvrsLj|B2fZ+g?57zL2k>LUopZ5VH!wo1Ore1;rVgZcr0p(Y6 zFfd4LU}69@R6rpzlY@alXbTfV0+PJo1}2930;mAYfC?yoI|l=U$`K}p2~a*eCj$fL z2_}XaP`)N71B2ojCWaSKzCR}egZu?1h8dg?2f^i`e3<+XD8Gu6fkE~GQ$0fj7eoU{ zf%*j|h6E%&$iNIJe<LRYgVq%$1_N%0dZ+;m4p2TwKS=!xC?6)T!GloG`+$kT0Lp*G z$-rRnq@Iak0#rbgi-AGp0~5mmD8Gq|fr0l66T=N8zRVXUh8Ix&8jw5>GlK#z#Db?> z3=E1g%nTY(K07x9gQN;Gg8`HelV1Skt8g<gh}1hUGn{}5RB$se@VYQFT!8W?a5FFn z#xOI0Dj!fB!uTJc@|!^N3Cs)<d=Lk`<z`@z%VB0vK;p~fFf(XC`2su)49W$}3;|Gn z9uEUUy<iD5Lj+WylZSypw1SzT0F7S(<*x_H*Dy0Ifb!XS85pE`m>CL$Ar4UCWnhq> zz|8PK6vFr6Wnkc)!p!gk$}b1i6Dyb*K=lQ*Zjb@z|EatT3_K?gl>>;+dV+cKL1{&1 zW(LN|j?$u&du&DOYZ(|Am_YS8EVY7aVg?2VJ#c%DkpbG@fypwMLd8K2fD1A(Ft|d+ zLFEgwIA~B1RF!E!D?gar2QY)N9-N=SY$)*^OfxcovK^QSCAy&&RDi2^s2~FagB(;G zl+6*M3=I5GaZvU~7SDl-gR(gTc(4X4s|J&RG)$nP3=FnV@eWAq9WD;)Z7?#hfZInP zK@cBAgIm)KjNmi`;=^zWBPbkLzzs`~7&xG<7#J8*pca7A07wFceW4ocp#so;3Yf>t zzzmMUCAK2$3mHHSJf_M04&suarVv;G1B?Z-L6CuM@_w)^OcZP-s1FQo;IU19?;tJ- zY9&DQf*Ri-mN+A*`NuL@-cg*9b+WmmY(2=6pz;hP3o--L?VJG(7#JUv+hOvcZYwBv z!}uUigK{g357H0HoG?B}Jt#B6_#pM5%m(Evf%^%d%mo!-0BHbaCKz9A@>fUY`VeR$ z0eKhHZU$8vAQd1!$Vylu0(lwar531q5FcdX1SCFatYHokALOJJX#6dxd_IOVPyvvI za+8-j=`)IMzUsuxrUh#Rf+Rp4(FSO~fbr#&<rP(x6a<AuCo}ncm9%8=adI+@H-yqg z7Er#$WJO<54MQ^s*T@t~Lnvb-2yFzV4JWtx%5fPRLPQM>C)XNFutUr>nEcV#eDVcp z-pLt$3QP=Qle_%nCcp5L;Bo+YlL0h}02a#dm*9d94KOG$fQ4T8OE5KvO=b$PWBMXC z*(tz|>4(_lrT{xG1<23>gNxW?FF(1-8i5jADUi`ah6!wwPX(Ik{(y|tF}#2lS)kS} zNE2iT05U=WiY`!!;+*U#Ev)+hGFAp|5rSkug90E~m=2H$AaQR71_rPW!3pLdK4g>v z#NwQM(NCN;3MQ|+09~Ge0n{4<x6VQ8VJ1F@>(~I*0cy2^RDj$7ie_{-fQAjgZV+_< sjd(CHFhIvD7(hBWCQl92=9&N+fMQ@^;9`J;k)H(TEU3`r$)0}l0M_HxLI3~& diff --git a/pkg/exporter/ipfix.go b/pkg/exporter/ipfix.go index c6c33e6d..ad059a73 100644 --- a/pkg/exporter/ipfix.go +++ b/pkg/exporter/ipfix.go @@ -39,6 +39,42 @@ func addElementToTemplate(log *logrus.Entry, elementName string, value []byte, e return nil } +func AddRecordValuesToTemplate(log *logrus.Entry, elements *[]entities.InfoElementWithValue) error { + err := addElementToTemplate(log, "octetDeltaCount", nil, elements) + if err != nil { + return err + } + err = addElementToTemplate(log, "tcpControlBits", nil, elements) + if err != nil { + return err + } + err = addElementToTemplate(log, "flowStartSeconds", nil, elements) + if err != nil { + return err + } + err = addElementToTemplate(log, "flowStartMilliseconds", nil, elements) + if err != nil { + return err + } + err = addElementToTemplate(log, "flowEndSeconds", nil, elements) + if err != nil { + return err + } + err = addElementToTemplate(log, "flowEndMilliseconds", nil, elements) + if err != nil { + return err + } + err = addElementToTemplate(log, "packetDeltaCount", nil, elements) + if err != nil { + return err + } + err = addElementToTemplate(log, "interfaceName", nil, elements) + if err != nil { + return err + } + return nil +} + func SendTemplateRecordv4(log *logrus.Entry, exporter *ipfixExporter.ExportingProcess) (uint16, []entities.InfoElementWithValue, error) { templateID := exporter.NewTemplateID() templateSet := entities.NewSet(false) @@ -84,35 +120,10 @@ func SendTemplateRecordv4(log *logrus.Entry, exporter *ipfixExporter.ExportingPr if err != nil { return 0, nil, err } - err = addElementToTemplate(log, "octetDeltaCount", nil, &elements) - if err != nil { - return 0, nil, err - } - err = addElementToTemplate(log, "flowStartSeconds", nil, &elements) - if err != nil { - return 0, nil, err - } - err = addElementToTemplate(log, "flowStartMilliseconds", nil, &elements) - if err != nil { - return 0, nil, err - } - err = addElementToTemplate(log, "flowEndSeconds", nil, &elements) - if err != nil { - return 0, nil, err - } - err = addElementToTemplate(log, "flowEndMilliseconds", nil, &elements) - if err != nil { - return 0, nil, err - } - err = addElementToTemplate(log, "packetDeltaCount", nil, &elements) - if err != nil { - return 0, nil, err - } - err = addElementToTemplate(log, "interfaceName", nil, &elements) + err = AddRecordValuesToTemplate(log, &elements) if err != nil { return 0, nil, err } - err = templateSet.AddRecord(elements, templateID) if err != nil { return 0, nil, err @@ -170,31 +181,7 @@ func SendTemplateRecordv6(log *logrus.Entry, exporter *ipfixExporter.ExportingPr if err != nil { return 0, nil, err } - err = addElementToTemplate(log, "octetDeltaCount", nil, &elements) - if err != nil { - return 0, nil, err - } - err = addElementToTemplate(log, "flowStartSeconds", nil, &elements) - if err != nil { - return 0, nil, err - } - err = addElementToTemplate(log, "flowStartMilliseconds", nil, &elements) - if err != nil { - return 0, nil, err - } - err = addElementToTemplate(log, "flowEndSeconds", nil, &elements) - if err != nil { - return 0, nil, err - } - err = addElementToTemplate(log, "flowEndMilliseconds", nil, &elements) - if err != nil { - return 0, nil, err - } - err = addElementToTemplate(log, "packetDeltaCount", nil, &elements) - if err != nil { - return 0, nil, err - } - err = addElementToTemplate(log, "interfaceName", nil, &elements) + err = AddRecordValuesToTemplate(log, &elements) if err != nil { return 0, nil, err } @@ -262,6 +249,27 @@ func setIPv4Address(ieValPtr *entities.InfoElementWithValue, ipAddress net.IP) { ieVal.SetIPAddressValue(ipAddress) } } +func setIERecordValue(record *flow.Record, ieValPtr *entities.InfoElementWithValue) { + ieVal := *ieValPtr + switch ieVal.GetName() { + case "octetDeltaCount": + ieVal.SetUnsigned64Value(record.Bytes) + case "tcpControlBits": + ieVal.SetUnsigned16Value(record.Flags) + case "flowStartSeconds": + ieVal.SetUnsigned32Value(uint32(record.TimeFlowStart.Unix())) + case "flowStartMilliseconds": + ieVal.SetUnsigned64Value(uint64(record.TimeFlowStart.UnixMilli())) + case "flowEndSeconds": + ieVal.SetUnsigned32Value(uint32(record.TimeFlowEnd.Unix())) + case "flowEndMilliseconds": + ieVal.SetUnsigned64Value(uint64(record.TimeFlowEnd.UnixMilli())) + case "packetDeltaCount": + ieVal.SetUnsigned64Value(uint64(record.Packets)) + case "interfaceName": + ieVal.SetStringValue(record.Interface) + } +} func setIEValue(record *flow.Record, ieValPtr *entities.InfoElementWithValue) { ieVal := *ieValPtr switch ieVal.GetName() { @@ -289,26 +297,12 @@ func setIEValue(record *flow.Record, ieValPtr *entities.InfoElementWithValue) { ieVal.SetUnsigned16Value(record.Transport.SrcPort) case "destinationTransportPort": ieVal.SetUnsigned16Value(record.Transport.DstPort) - case "octetDeltaCount": - ieVal.SetUnsigned64Value(record.Bytes) - case "flowStartSeconds": - ieVal.SetUnsigned32Value(uint32(record.TimeFlowStart.Unix())) - case "flowStartMilliseconds": - ieVal.SetUnsigned64Value(uint64(record.TimeFlowStart.UnixMilli())) - case "flowEndSeconds": - ieVal.SetUnsigned32Value(uint32(record.TimeFlowEnd.Unix())) - case "flowEndMilliseconds": - ieVal.SetUnsigned64Value(uint64(record.TimeFlowEnd.UnixMilli())) - case "packetDeltaCount": - ieVal.SetUnsigned64Value(uint64(record.Packets)) - case "interfaceName": - ieVal.SetStringValue(record.Interface) } - } func setEntities(record *flow.Record, elements *[]entities.InfoElementWithValue) { for _, ieVal := range *elements { setIEValue(record, &ieVal) + setIERecordValue(record, &ieVal) } } func (ipf *IPFIX) sendDataRecord(log *logrus.Entry, record *flow.Record, v6 bool) error { diff --git a/pkg/exporter/kafka_proto_test.go b/pkg/exporter/kafka_proto_test.go index 0093df1b..485b4c24 100644 --- a/pkg/exporter/kafka_proto_test.go +++ b/pkg/exporter/kafka_proto_test.go @@ -24,7 +24,7 @@ func IPAddrFromNetIP(netIP net.IP) flow.IPAddr { func TestProtoConversion(t *testing.T) { wc := writerCapturer{} kj := KafkaProto{Writer: &wc} - input := make(chan []*flow.Record, 10) + input := make(chan []*flow.Record, 11) record := flow.Record{} record.EthProtocol = 3 record.Direction = 1 @@ -39,6 +39,7 @@ func TestProtoConversion(t *testing.T) { record.TimeFlowEnd = time.Now() record.Bytes = 789 record.Packets = 987 + record.Flags = uint16(1) record.Interface = "veth0" input <- []*flow.Record{&record} @@ -61,6 +62,7 @@ func TestProtoConversion(t *testing.T) { assert.Equal(t, record.TimeFlowEnd.UnixMilli(), r.TimeFlowEnd.AsTime().UnixMilli()) assert.EqualValues(t, 789, r.Bytes) assert.EqualValues(t, 987, r.Packets) + assert.EqualValues(t, uint16(1), r.Flags) assert.Equal(t, "veth0", r.Interface) } diff --git a/pkg/exporter/proto.go b/pkg/exporter/proto.go index a47048b9..f6374341 100644 --- a/pkg/exporter/proto.go +++ b/pkg/exporter/proto.go @@ -64,9 +64,10 @@ func v4FlowToPB(fr *flow.Record) *pbflow.Record { Nanos: int32(fr.TimeFlowEnd.Nanosecond()), }, Packets: uint64(fr.Packets), - Interface: fr.Interface, Duplicate: fr.Duplicate, AgentIp: agentIP(fr.AgentIP), + Flags: uint32(fr.Flags), + Interface: string(fr.Interface), } } @@ -97,6 +98,7 @@ func v6FlowToPB(fr *flow.Record) *pbflow.Record { Nanos: int32(fr.TimeFlowEnd.Nanosecond()), }, Packets: uint64(fr.Packets), + Flags: uint32(fr.Flags), Interface: fr.Interface, Duplicate: fr.Duplicate, AgentIp: agentIP(fr.AgentIP), diff --git a/pkg/flow/account_test.go b/pkg/flow/account_test.go index 2bf2bf04..2e30ca79 100644 --- a/pkg/flow/account_test.go +++ b/pkg/flow/account_test.go @@ -55,19 +55,19 @@ func TestEvict_MaxEntries(t *testing.T) { inputs <- &RawRecord{ RecordKey: k1, RecordMetrics: RecordMetrics{ - Bytes: 123, Packets: 1, StartMonoTimeNs: 123, EndMonoTimeNs: 123, + Bytes: 123, Packets: 1, StartMonoTimeNs: 123, EndMonoTimeNs: 123, Flags: 1, }, } inputs <- &RawRecord{ RecordKey: k2, RecordMetrics: RecordMetrics{ - Bytes: 456, Packets: 1, StartMonoTimeNs: 456, EndMonoTimeNs: 456, + Bytes: 456, Packets: 1, StartMonoTimeNs: 456, EndMonoTimeNs: 456, Flags: 1, }, } inputs <- &RawRecord{ RecordKey: k1, RecordMetrics: RecordMetrics{ - Bytes: 321, Packets: 1, StartMonoTimeNs: 789, EndMonoTimeNs: 789, + Bytes: 321, Packets: 1, StartMonoTimeNs: 789, EndMonoTimeNs: 789, Flags: 1, }, } requireNoEviction(t, evictor) @@ -76,7 +76,7 @@ func TestEvict_MaxEntries(t *testing.T) { inputs <- &RawRecord{ RecordKey: k3, RecordMetrics: RecordMetrics{ - Bytes: 111, Packets: 1, StartMonoTimeNs: 888, EndMonoTimeNs: 888, + Bytes: 111, Packets: 1, StartMonoTimeNs: 888, EndMonoTimeNs: 888, Flags: 1, }, } @@ -96,7 +96,7 @@ func TestEvict_MaxEntries(t *testing.T) { RawRecord: RawRecord{ RecordKey: k1, RecordMetrics: RecordMetrics{ - Bytes: 444, Packets: 2, StartMonoTimeNs: 123, EndMonoTimeNs: 789, + Bytes: 444, Packets: 2, StartMonoTimeNs: 123, EndMonoTimeNs: 789, Flags: 1, }, }, TimeFlowStart: now.Add(-(1000 - 123) * time.Nanosecond), @@ -106,7 +106,7 @@ func TestEvict_MaxEntries(t *testing.T) { RawRecord: RawRecord{ RecordKey: k2, RecordMetrics: RecordMetrics{ - Bytes: 456, Packets: 1, StartMonoTimeNs: 456, EndMonoTimeNs: 456, + Bytes: 456, Packets: 1, StartMonoTimeNs: 456, EndMonoTimeNs: 456, Flags: 1, }, }, TimeFlowStart: now.Add(-(1000 - 456) * time.Nanosecond), @@ -132,19 +132,19 @@ func TestEvict_Period(t *testing.T) { inputs <- &RawRecord{ RecordKey: k1, RecordMetrics: RecordMetrics{ - Bytes: 10, Packets: 1, StartMonoTimeNs: 123, EndMonoTimeNs: 123, + Bytes: 10, Packets: 1, StartMonoTimeNs: 123, EndMonoTimeNs: 123, Flags: 1, }, } inputs <- &RawRecord{ RecordKey: k1, RecordMetrics: RecordMetrics{ - Bytes: 10, Packets: 1, StartMonoTimeNs: 456, EndMonoTimeNs: 456, + Bytes: 10, Packets: 1, StartMonoTimeNs: 456, EndMonoTimeNs: 456, Flags: 1, }, } inputs <- &RawRecord{ RecordKey: k1, RecordMetrics: RecordMetrics{ - Bytes: 10, Packets: 1, StartMonoTimeNs: 789, EndMonoTimeNs: 789, + Bytes: 10, Packets: 1, StartMonoTimeNs: 789, EndMonoTimeNs: 789, Flags: 1, }, } // Forcing at least one eviction here @@ -152,13 +152,13 @@ func TestEvict_Period(t *testing.T) { inputs <- &RawRecord{ RecordKey: k1, RecordMetrics: RecordMetrics{ - Bytes: 10, Packets: 1, StartMonoTimeNs: 1123, EndMonoTimeNs: 1123, + Bytes: 10, Packets: 1, StartMonoTimeNs: 1123, EndMonoTimeNs: 1123, Flags: 1, }, } inputs <- &RawRecord{ RecordKey: k1, RecordMetrics: RecordMetrics{ - Bytes: 10, Packets: 1, StartMonoTimeNs: 1456, EndMonoTimeNs: 1456, + Bytes: 10, Packets: 1, StartMonoTimeNs: 1456, EndMonoTimeNs: 1456, Flags: 1, }, } @@ -174,6 +174,7 @@ func TestEvict_Period(t *testing.T) { Packets: 3, StartMonoTimeNs: 123, EndMonoTimeNs: 789, + Flags: 1, }, }, TimeFlowStart: now.Add(-1000 + 123), @@ -189,6 +190,7 @@ func TestEvict_Period(t *testing.T) { Packets: 2, StartMonoTimeNs: 1123, EndMonoTimeNs: 1456, + Flags: 1, }, }, TimeFlowStart: now.Add(-1000 + 1123), diff --git a/pkg/flow/deduper_test.go b/pkg/flow/deduper_test.go index 7f3176ff..ec359e7b 100644 --- a/pkg/flow/deduper_test.go +++ b/pkg/flow/deduper_test.go @@ -13,26 +13,26 @@ var ( EthProtocol: 1, Direction: 1, Transport: Transport{SrcPort: 123, DstPort: 456}, DataLink: DataLink{DstMac: MacAddr{0x1}, SrcMac: MacAddr{0x1}}, IFIndex: 1, }, RecordMetrics: RecordMetrics{ - Packets: 2, Bytes: 456, + Packets: 2, Bytes: 456, Flags: 1, }}, Interface: "eth0"} oneIf2 = &Record{RawRecord: RawRecord{RecordKey: RecordKey{ EthProtocol: 1, Direction: 1, Transport: Transport{SrcPort: 123, DstPort: 456}, DataLink: DataLink{DstMac: MacAddr{0x2}, SrcMac: MacAddr{0x2}}, IFIndex: 2, }, RecordMetrics: RecordMetrics{ - Packets: 2, Bytes: 456, + Packets: 2, Bytes: 456, Flags: 1, }}, Interface: "123456789"} // another fow from 2 different interfaces and directions twoIf1 = &Record{RawRecord: RawRecord{RecordKey: RecordKey{ EthProtocol: 1, Direction: 1, Transport: Transport{SrcPort: 333, DstPort: 456}, DataLink: DataLink{DstMac: MacAddr{0x1}, SrcMac: MacAddr{0x1}}, IFIndex: 1, }, RecordMetrics: RecordMetrics{ - Packets: 2, Bytes: 456, + Packets: 2, Bytes: 456, Flags: 1, }}, Interface: "eth0"} twoIf2 = &Record{RawRecord: RawRecord{RecordKey: RecordKey{ EthProtocol: 1, Direction: 0, Transport: Transport{SrcPort: 333, DstPort: 456}, DataLink: DataLink{DstMac: MacAddr{0x2}, SrcMac: MacAddr{0x2}}, IFIndex: 2, }, RecordMetrics: RecordMetrics{ - Packets: 2, Bytes: 456, + Packets: 2, Bytes: 456, Flags: 1, }}, Interface: "123456789"} ) diff --git a/pkg/flow/record.go b/pkg/flow/record.go index 665f4ed2..4751c04c 100644 --- a/pkg/flow/record.go +++ b/pkg/flow/record.go @@ -65,8 +65,8 @@ type RecordMetrics struct { // and monotime.Now() (user space) StartMonoTimeNs uint64 EndMonoTimeNs uint64 - - Errno uint8 + Flags uint16 + Errno uint8 } // record structure as parsed from eBPF @@ -124,6 +124,7 @@ func (r *RecordMetrics) Accumulate(src *RecordMetrics) { } r.Bytes += src.Bytes r.Packets += src.Packets + r.Flags |= src.Flags } // IP returns the net.IP equivalent object diff --git a/pkg/flow/record_test.go b/pkg/flow/record_test.go index e26618aa..de782e71 100644 --- a/pkg/flow/record_test.go +++ b/pkg/flow/record_test.go @@ -26,7 +26,9 @@ func TestRecordBinaryEncoding(t *testing.T) { 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, // u64 bytes 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, // u64 flow_start_time 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, // u64 flow_end_time + 0x13, 0x14, //flags 0x33, // u8 errno + })) require.NoError(t, err) @@ -54,6 +56,7 @@ func TestRecordBinaryEncoding(t *testing.T) { Bytes: 0x1a19181716151413, StartMonoTimeNs: 0x1a19181716151413, EndMonoTimeNs: 0x1a19181716151413, + Flags: 0x1413, Errno: 0x33, }, }, *fr) diff --git a/pkg/flow/tracer_map_test.go b/pkg/flow/tracer_map_test.go index 74c8c3d2..0518159e 100644 --- a/pkg/flow/tracer_map_test.go +++ b/pkg/flow/tracer_map_test.go @@ -14,23 +14,23 @@ func TestPacketAggregation(t *testing.T) { } tcs := []testCase{{ input: []RecordMetrics{ - {Packets: 0, Bytes: 0, StartMonoTimeNs: 0, EndMonoTimeNs: 0}, - {Packets: 0x7, Bytes: 0x22d, StartMonoTimeNs: 0x176a790b240b, EndMonoTimeNs: 0x176a792a755b}, - {Packets: 0x0, Bytes: 0x0, StartMonoTimeNs: 0x0, EndMonoTimeNs: 0x0}, - {Packets: 0x0, Bytes: 0x0, StartMonoTimeNs: 0x0, EndMonoTimeNs: 0x0}, + {Packets: 0, Bytes: 0, StartMonoTimeNs: 0, EndMonoTimeNs: 0, Flags: 1}, + {Packets: 0x7, Bytes: 0x22d, StartMonoTimeNs: 0x176a790b240b, EndMonoTimeNs: 0x176a792a755b, Flags: 1}, + {Packets: 0x0, Bytes: 0x0, StartMonoTimeNs: 0x0, EndMonoTimeNs: 0x0, Flags: 1}, + {Packets: 0x0, Bytes: 0x0, StartMonoTimeNs: 0x0, EndMonoTimeNs: 0x0, Flags: 1}, }, expected: RecordMetrics{ - Packets: 0x7, Bytes: 0x22d, StartMonoTimeNs: 0x176a790b240b, EndMonoTimeNs: 0x176a792a755b, + Packets: 0x7, Bytes: 0x22d, StartMonoTimeNs: 0x176a790b240b, EndMonoTimeNs: 0x176a792a755b, Flags: 1, }, }, { input: []RecordMetrics{ - {Packets: 0x3, Bytes: 0x5c4, StartMonoTimeNs: 0x17f3e9613a7f, EndMonoTimeNs: 0x17f3e979816e}, - {Packets: 0x2, Bytes: 0x8c, StartMonoTimeNs: 0x17f3e9633a7f, EndMonoTimeNs: 0x17f3e96f164e}, - {Packets: 0x0, Bytes: 0x0, StartMonoTimeNs: 0x0, EndMonoTimeNs: 0x0}, - {Packets: 0x0, Bytes: 0x0, StartMonoTimeNs: 0x0, EndMonoTimeNs: 0x0}, + {Packets: 0x3, Bytes: 0x5c4, StartMonoTimeNs: 0x17f3e9613a7f, EndMonoTimeNs: 0x17f3e979816e, Flags: 1}, + {Packets: 0x2, Bytes: 0x8c, StartMonoTimeNs: 0x17f3e9633a7f, EndMonoTimeNs: 0x17f3e96f164e, Flags: 1}, + {Packets: 0x0, Bytes: 0x0, StartMonoTimeNs: 0x0, EndMonoTimeNs: 0x0, Flags: 1}, + {Packets: 0x0, Bytes: 0x0, StartMonoTimeNs: 0x0, EndMonoTimeNs: 0x0, Flags: 1}, }, expected: RecordMetrics{ - Packets: 0x5, Bytes: 0x5c4 + 0x8c, StartMonoTimeNs: 0x17f3e9613a7f, EndMonoTimeNs: 0x17f3e979816e, + Packets: 0x5, Bytes: 0x5c4 + 0x8c, StartMonoTimeNs: 0x17f3e9613a7f, EndMonoTimeNs: 0x17f3e979816e, Flags: 1, }, }} ft := MapTracer{} diff --git a/pkg/grpc/grpc_test.go b/pkg/grpc/grpc_test.go index eb2184ab..fb858433 100644 --- a/pkg/grpc/grpc_test.go +++ b/pkg/grpc/grpc_test.go @@ -29,7 +29,7 @@ func TestGRPCCommunication(t *testing.T) { go func() { _, err = client.Send(context.Background(), &pbflow.Records{Entries: []*pbflow.Record{{ - EthProtocol: 123, Bytes: 456, Network: &pbflow.Network{ + EthProtocol: 123, Flags: 1, Bytes: 456, Network: &pbflow.Network{ SrcAddr: &pbflow.IP{ IpFamily: &pbflow.IP_Ipv4{Ipv4: 0x11223344}, }, @@ -43,7 +43,7 @@ func TestGRPCCommunication(t *testing.T) { require.NoError(t, err) _, err = client.Send(context.Background(), &pbflow.Records{Entries: []*pbflow.Record{{ - EthProtocol: 789, Bytes: 101, Network: &pbflow.Network{ + EthProtocol: 789, Flags: 1, Bytes: 101, Network: &pbflow.Network{ SrcAddr: &pbflow.IP{ IpFamily: &pbflow.IP_Ipv4{Ipv4: 0x44332211}, }, @@ -66,6 +66,7 @@ func TestGRPCCommunication(t *testing.T) { assert.Len(t, rs.Entries, 1) r := rs.Entries[0] assert.EqualValues(t, 123, r.EthProtocol) + assert.EqualValues(t, 1, r.Flags) assert.EqualValues(t, 456, r.Bytes) assert.EqualValues(t, 0x11223344, r.GetNetwork().GetSrcAddr().GetIpv4()) assert.EqualValues(t, 0x55667788, r.GetNetwork().GetDstAddr().GetIpv4()) @@ -78,6 +79,7 @@ func TestGRPCCommunication(t *testing.T) { assert.Len(t, rs.Entries, 1) r = rs.Entries[0] assert.EqualValues(t, 789, r.EthProtocol) + assert.EqualValues(t, 1, r.Flags) assert.EqualValues(t, 101, r.Bytes) assert.EqualValues(t, 0x44332211, r.GetNetwork().GetSrcAddr().GetIpv4()) assert.EqualValues(t, uint64(0x88776655), r.GetNetwork().GetDstAddr().GetIpv4()) @@ -114,7 +116,7 @@ func TestConstructorOptions(t *testing.T) { go func() { _, err = client.Send(context.Background(), - &pbflow.Records{Entries: []*pbflow.Record{{EthProtocol: 123, Bytes: 456}}}) + &pbflow.Records{Entries: []*pbflow.Record{{EthProtocol: 123, Bytes: 456, Flags: 1}}}) require.NoError(t, err) }() @@ -140,6 +142,7 @@ func BenchmarkGRPCCommunication(b *testing.B) { f := &pbflow.Record{ EthProtocol: 2048, Bytes: 456, + Flags: 1, Direction: pbflow.Direction_EGRESS, TimeFlowStart: timestamppb.Now(), TimeFlowEnd: timestamppb.Now(), diff --git a/pkg/pbflow/flow.pb.go b/pkg/pbflow/flow.pb.go index 4458513e..6306ac87 100644 --- a/pkg/pbflow/flow.pb.go +++ b/pkg/pbflow/flow.pb.go @@ -1,15 +1,15 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.1 -// protoc v3.19.4 +// protoc-gen-go v1.27.1 +// protoc v3.12.4 // source: proto/flow.proto package pbflow import ( + timestamp "github.com/golang/protobuf/ptypes/timestamp" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" - timestamppb "google.golang.org/protobuf/types/known/timestamppb" reflect "reflect" sync "sync" ) @@ -162,10 +162,10 @@ type Record struct { // protocol as defined by ETH_P_* in linux/if_ether.h // https://github.com/torvalds/linux/blob/master/include/uapi/linux/if_ether.h - EthProtocol uint32 `protobuf:"varint,1,opt,name=eth_protocol,json=ethProtocol,proto3" json:"eth_protocol,omitempty"` - Direction Direction `protobuf:"varint,2,opt,name=direction,proto3,enum=pbflow.Direction" json:"direction,omitempty"` - TimeFlowStart *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=time_flow_start,json=timeFlowStart,proto3" json:"time_flow_start,omitempty"` - TimeFlowEnd *timestamppb.Timestamp `protobuf:"bytes,4,opt,name=time_flow_end,json=timeFlowEnd,proto3" json:"time_flow_end,omitempty"` + EthProtocol uint32 `protobuf:"varint,1,opt,name=eth_protocol,json=ethProtocol,proto3" json:"eth_protocol,omitempty"` + Direction Direction `protobuf:"varint,2,opt,name=direction,proto3,enum=pbflow.Direction" json:"direction,omitempty"` + TimeFlowStart *timestamp.Timestamp `protobuf:"bytes,3,opt,name=time_flow_start,json=timeFlowStart,proto3" json:"time_flow_start,omitempty"` + TimeFlowEnd *timestamp.Timestamp `protobuf:"bytes,4,opt,name=time_flow_end,json=timeFlowEnd,proto3" json:"time_flow_end,omitempty"` // OSI-layer attributes DataLink *DataLink `protobuf:"bytes,5,opt,name=data_link,json=dataLink,proto3" json:"data_link,omitempty"` Network *Network `protobuf:"bytes,6,opt,name=network,proto3" json:"network,omitempty"` @@ -177,7 +177,8 @@ type Record struct { // From all the duplicate flows, one will set this value to false and the rest will be true. Duplicate bool `protobuf:"varint,11,opt,name=duplicate,proto3" json:"duplicate,omitempty"` // Agent IP address to help identifying the source of the flow - AgentIp *IP `protobuf:"bytes,12,opt,name=agent_ip,json=agentIp,proto3" json:"agent_ip,omitempty"` + AgentIp *IP `protobuf:"bytes,12,opt,name=agent_ip,json=agentIp,proto3" json:"agent_ip,omitempty"` + Flags uint32 `protobuf:"varint,13,opt,name=flags,proto3" json:"flags,omitempty"` } func (x *Record) Reset() { @@ -226,14 +227,14 @@ func (x *Record) GetDirection() Direction { return Direction_INGRESS } -func (x *Record) GetTimeFlowStart() *timestamppb.Timestamp { +func (x *Record) GetTimeFlowStart() *timestamp.Timestamp { if x != nil { return x.TimeFlowStart } return nil } -func (x *Record) GetTimeFlowEnd() *timestamppb.Timestamp { +func (x *Record) GetTimeFlowEnd() *timestamp.Timestamp { if x != nil { return x.TimeFlowEnd } @@ -296,6 +297,13 @@ func (x *Record) GetAgentIp() *IP { return nil } +func (x *Record) GetFlags() uint32 { + if x != nil { + return x.Flags + } + return 0 +} + type DataLink struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -562,7 +570,7 @@ var file_proto_flow_proto_rawDesc = []byte{ 0x07, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x12, 0x28, 0x0a, 0x07, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x62, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x52, 0x07, 0x65, 0x6e, 0x74, 0x72, 0x69, - 0x65, 0x73, 0x22, 0xfe, 0x03, 0x0a, 0x06, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x12, 0x21, 0x0a, + 0x65, 0x73, 0x22, 0x94, 0x04, 0x0a, 0x06, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x65, 0x74, 0x68, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x65, 0x74, 0x68, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x2f, 0x0a, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, @@ -594,34 +602,35 @@ var file_proto_flow_proto_rawDesc = []byte{ 0x08, 0x52, 0x09, 0x64, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x25, 0x0a, 0x08, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x70, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x70, 0x62, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x49, 0x50, 0x52, 0x07, 0x61, 0x67, 0x65, 0x6e, - 0x74, 0x49, 0x70, 0x22, 0x3c, 0x0a, 0x08, 0x44, 0x61, 0x74, 0x61, 0x4c, 0x69, 0x6e, 0x6b, 0x12, - 0x17, 0x0a, 0x07, 0x73, 0x72, 0x63, 0x5f, 0x6d, 0x61, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, - 0x52, 0x06, 0x73, 0x72, 0x63, 0x4d, 0x61, 0x63, 0x12, 0x17, 0x0a, 0x07, 0x64, 0x73, 0x74, 0x5f, - 0x6d, 0x61, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x64, 0x73, 0x74, 0x4d, 0x61, - 0x63, 0x22, 0x57, 0x0a, 0x07, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x12, 0x25, 0x0a, 0x08, - 0x73, 0x72, 0x63, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, - 0x2e, 0x70, 0x62, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x49, 0x50, 0x52, 0x07, 0x73, 0x72, 0x63, 0x41, - 0x64, 0x64, 0x72, 0x12, 0x25, 0x0a, 0x08, 0x64, 0x73, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x70, 0x62, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x49, - 0x50, 0x52, 0x07, 0x64, 0x73, 0x74, 0x41, 0x64, 0x64, 0x72, 0x22, 0x3d, 0x0a, 0x02, 0x49, 0x50, - 0x12, 0x14, 0x0a, 0x04, 0x69, 0x70, 0x76, 0x34, 0x18, 0x01, 0x20, 0x01, 0x28, 0x07, 0x48, 0x00, - 0x52, 0x04, 0x69, 0x70, 0x76, 0x34, 0x12, 0x14, 0x0a, 0x04, 0x69, 0x70, 0x76, 0x36, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x04, 0x69, 0x70, 0x76, 0x36, 0x42, 0x0b, 0x0a, 0x09, - 0x69, 0x70, 0x5f, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x22, 0x5d, 0x0a, 0x09, 0x54, 0x72, 0x61, - 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x72, 0x63, 0x5f, 0x70, 0x6f, - 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x73, 0x72, 0x63, 0x50, 0x6f, 0x72, - 0x74, 0x12, 0x19, 0x0a, 0x08, 0x64, 0x73, 0x74, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0d, 0x52, 0x07, 0x64, 0x73, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x1a, 0x0a, 0x08, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2a, 0x24, 0x0a, 0x09, 0x44, 0x69, 0x72, 0x65, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0b, 0x0a, 0x07, 0x49, 0x4e, 0x47, 0x52, 0x45, 0x53, 0x53, - 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x45, 0x47, 0x52, 0x45, 0x53, 0x53, 0x10, 0x01, 0x32, 0x3e, - 0x0a, 0x09, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x31, 0x0a, 0x04, 0x53, - 0x65, 0x6e, 0x64, 0x12, 0x0f, 0x2e, 0x70, 0x62, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x52, 0x65, 0x63, - 0x6f, 0x72, 0x64, 0x73, 0x1a, 0x16, 0x2e, 0x70, 0x62, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x43, 0x6f, - 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x42, 0x0a, - 0x5a, 0x08, 0x2e, 0x2f, 0x70, 0x62, 0x66, 0x6c, 0x6f, 0x77, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, + 0x74, 0x49, 0x70, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x0d, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x22, 0x3c, 0x0a, 0x08, 0x44, 0x61, 0x74, + 0x61, 0x4c, 0x69, 0x6e, 0x6b, 0x12, 0x17, 0x0a, 0x07, 0x73, 0x72, 0x63, 0x5f, 0x6d, 0x61, 0x63, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x73, 0x72, 0x63, 0x4d, 0x61, 0x63, 0x12, 0x17, + 0x0a, 0x07, 0x64, 0x73, 0x74, 0x5f, 0x6d, 0x61, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x06, 0x64, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x22, 0x57, 0x0a, 0x07, 0x4e, 0x65, 0x74, 0x77, 0x6f, + 0x72, 0x6b, 0x12, 0x25, 0x0a, 0x08, 0x73, 0x72, 0x63, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x70, 0x62, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x49, 0x50, + 0x52, 0x07, 0x73, 0x72, 0x63, 0x41, 0x64, 0x64, 0x72, 0x12, 0x25, 0x0a, 0x08, 0x64, 0x73, 0x74, + 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x70, 0x62, + 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x49, 0x50, 0x52, 0x07, 0x64, 0x73, 0x74, 0x41, 0x64, 0x64, 0x72, + 0x22, 0x3d, 0x0a, 0x02, 0x49, 0x50, 0x12, 0x14, 0x0a, 0x04, 0x69, 0x70, 0x76, 0x34, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x07, 0x48, 0x00, 0x52, 0x04, 0x69, 0x70, 0x76, 0x34, 0x12, 0x14, 0x0a, 0x04, + 0x69, 0x70, 0x76, 0x36, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x04, 0x69, 0x70, + 0x76, 0x36, 0x42, 0x0b, 0x0a, 0x09, 0x69, 0x70, 0x5f, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x22, + 0x5d, 0x0a, 0x09, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x19, 0x0a, 0x08, + 0x73, 0x72, 0x63, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, + 0x73, 0x72, 0x63, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x64, 0x73, 0x74, 0x5f, 0x70, + 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x64, 0x73, 0x74, 0x50, 0x6f, + 0x72, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2a, 0x24, + 0x0a, 0x09, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0b, 0x0a, 0x07, 0x49, + 0x4e, 0x47, 0x52, 0x45, 0x53, 0x53, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x45, 0x47, 0x52, 0x45, + 0x53, 0x53, 0x10, 0x01, 0x32, 0x3e, 0x0a, 0x09, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x6f, + 0x72, 0x12, 0x31, 0x0a, 0x04, 0x53, 0x65, 0x6e, 0x64, 0x12, 0x0f, 0x2e, 0x70, 0x62, 0x66, 0x6c, + 0x6f, 0x77, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x1a, 0x16, 0x2e, 0x70, 0x62, 0x66, + 0x6c, 0x6f, 0x77, 0x2e, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x70, + 0x6c, 0x79, 0x22, 0x00, 0x42, 0x0a, 0x5a, 0x08, 0x2e, 0x2f, 0x70, 0x62, 0x66, 0x6c, 0x6f, 0x77, + 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -639,15 +648,15 @@ func file_proto_flow_proto_rawDescGZIP() []byte { var file_proto_flow_proto_enumTypes = make([]protoimpl.EnumInfo, 1) var file_proto_flow_proto_msgTypes = make([]protoimpl.MessageInfo, 7) var file_proto_flow_proto_goTypes = []interface{}{ - (Direction)(0), // 0: pbflow.Direction - (*CollectorReply)(nil), // 1: pbflow.CollectorReply - (*Records)(nil), // 2: pbflow.Records - (*Record)(nil), // 3: pbflow.Record - (*DataLink)(nil), // 4: pbflow.DataLink - (*Network)(nil), // 5: pbflow.Network - (*IP)(nil), // 6: pbflow.IP - (*Transport)(nil), // 7: pbflow.Transport - (*timestamppb.Timestamp)(nil), // 8: google.protobuf.Timestamp + (Direction)(0), // 0: pbflow.Direction + (*CollectorReply)(nil), // 1: pbflow.CollectorReply + (*Records)(nil), // 2: pbflow.Records + (*Record)(nil), // 3: pbflow.Record + (*DataLink)(nil), // 4: pbflow.DataLink + (*Network)(nil), // 5: pbflow.Network + (*IP)(nil), // 6: pbflow.IP + (*Transport)(nil), // 7: pbflow.Transport + (*timestamp.Timestamp)(nil), // 8: google.protobuf.Timestamp } var file_proto_flow_proto_depIdxs = []int32{ 3, // 0: pbflow.Records.entries:type_name -> pbflow.Record diff --git a/pkg/pbflow/flow_grpc.pb.go b/pkg/pbflow/flow_grpc.pb.go index 11aee366..9b91b5ef 100644 --- a/pkg/pbflow/flow_grpc.pb.go +++ b/pkg/pbflow/flow_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.2.0 -// - protoc v3.19.4 +// - protoc v3.12.4 // source: proto/flow.proto package pbflow diff --git a/proto/flow.proto b/proto/flow.proto index 8b5994ee..9e291f72 100644 --- a/proto/flow.proto +++ b/proto/flow.proto @@ -40,6 +40,7 @@ message Record { // Agent IP address to help identifying the source of the flow IP agent_ip = 12; + uint32 flags = 13; } message DataLink { -- GitLab