From d7adc48f0cde89f420b5fe3e37c0becb1b7390ec Mon Sep 17 00:00:00 2001 From: Pravein Govindan Kannan <pravein.govindan.kannan@ibm.com> Date: Mon, 28 Nov 2022 17:06:23 +0530 Subject: [PATCH] Initial payload export from bpf using skb_o/p --- bpf/flow.h | 5 +++++ bpf/flows.c | 34 +++++++++++++++++++++++++++++++++- pkg/ebpf/bpf_bpfeb.go | 9 +++++++++ pkg/ebpf/bpf_bpfeb.o | Bin 17424 -> 19584 bytes pkg/ebpf/bpf_bpfel.go | 9 +++++++++ pkg/ebpf/bpf_bpfel.o | Bin 17520 -> 19680 bytes 6 files changed, 56 insertions(+), 1 deletion(-) diff --git a/bpf/flow.h b/bpf/flow.h index 1248838b..a5629d4d 100644 --- a/bpf/flow.h +++ b/bpf/flow.h @@ -51,4 +51,9 @@ typedef struct flow_record_t { flow_id id; flow_metrics metrics; } __attribute__((packed)) flow_record; + +typedef struct payload_meta_t { + u32 if_index; + u32 pkt_len; +} __attribute__((packed)) payload_meta; #endif diff --git a/bpf/flows.c b/bpf/flows.c index 790f24b8..8f06e281 100644 --- a/bpf/flows.c +++ b/bpf/flows.c @@ -48,6 +48,14 @@ struct { __uint(max_entries, 1 << 24); } direct_flows SEC(".maps"); + +// Perf Buffer to submit packet payloads to userspace +struct { + __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); + __uint(key_size, sizeof(int)); + __uint(value_size, sizeof(int)); +} packet_payloads SEC(".maps"); + // Key: the flow identifier. Value: the flow metrics for that identifier. // The userspace will aggregate them into a single flow. struct { @@ -58,7 +66,9 @@ struct { // Constant definitions, to be overridden by the invoker volatile const u32 sampling = 0; -volatile const u8 trace_messages = 0; +volatile const u8 trace_messages = 0; +volatile const u32 payload_size = 64; + const u8 ip4in6[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff}; @@ -232,6 +242,28 @@ static inline int flow_monitor(struct __sk_buff *skb, u8 direction) { return TC_ACT_OK; } + +static inline int export_packet_payload (struct __sk_buff *skb) { + void *data_end = (void *)(long)skb->data_end; + void *data = (void *)(long)skb->data; + payload_meta meta; + + meta.if_index = skb->ifindex; + meta.pkt_len = data_end - data; + bpf_skb_output(skb, &packet_payloads, ((u64) meta.pkt_len << 32) | BPF_F_CURRENT_CPU, &meta, sizeof(meta)); + return TC_ACT_OK; +} + +SEC("pano_ingress") +int pano_ingress_parse (struct __sk_buff *skb) { + return export_packet_payload(skb); +} + +SEC("pano_egress") +int pano_egress_parse (struct __sk_buff *skb) { + return export_packet_payload(skb); +} + SEC("tc_ingress") int ingress_flow_parse (struct __sk_buff *skb) { return flow_monitor(skb, INGRESS); diff --git a/pkg/ebpf/bpf_bpfeb.go b/pkg/ebpf/bpf_bpfeb.go index 4c4e7308..c9056a6d 100644 --- a/pkg/ebpf/bpf_bpfeb.go +++ b/pkg/ebpf/bpf_bpfeb.go @@ -56,6 +56,8 @@ type bpfSpecs struct { type bpfProgramSpecs struct { EgressFlowParse *ebpf.ProgramSpec `ebpf:"egress_flow_parse"` IngressFlowParse *ebpf.ProgramSpec `ebpf:"ingress_flow_parse"` + PanoEgressParse *ebpf.ProgramSpec `ebpf:"pano_egress_parse"` + PanoIngressParse *ebpf.ProgramSpec `ebpf:"pano_ingress_parse"` } // bpfMapSpecs contains maps before they are loaded into the kernel. @@ -64,6 +66,7 @@ type bpfProgramSpecs struct { type bpfMapSpecs struct { AggregatedFlows *ebpf.MapSpec `ebpf:"aggregated_flows"` DirectFlows *ebpf.MapSpec `ebpf:"direct_flows"` + PacketPayloads *ebpf.MapSpec `ebpf:"packet_payloads"` } // bpfObjects contains all objects after they have been loaded into the kernel. @@ -87,12 +90,14 @@ func (o *bpfObjects) Close() error { type bpfMaps struct { AggregatedFlows *ebpf.Map `ebpf:"aggregated_flows"` DirectFlows *ebpf.Map `ebpf:"direct_flows"` + PacketPayloads *ebpf.Map `ebpf:"packet_payloads"` } func (m *bpfMaps) Close() error { return _BpfClose( m.AggregatedFlows, m.DirectFlows, + m.PacketPayloads, ) } @@ -102,12 +107,16 @@ func (m *bpfMaps) Close() error { type bpfPrograms struct { EgressFlowParse *ebpf.Program `ebpf:"egress_flow_parse"` IngressFlowParse *ebpf.Program `ebpf:"ingress_flow_parse"` + PanoEgressParse *ebpf.Program `ebpf:"pano_egress_parse"` + PanoIngressParse *ebpf.Program `ebpf:"pano_ingress_parse"` } func (p *bpfPrograms) Close() error { return _BpfClose( p.EgressFlowParse, p.IngressFlowParse, + p.PanoEgressParse, + p.PanoIngressParse, ) } diff --git a/pkg/ebpf/bpf_bpfeb.o b/pkg/ebpf/bpf_bpfeb.o index ee6465770f750f986efe7ab54426cac2f1b26477..a1ca06ca391a25745d2e6da4d9d301d991d8a8be 100644 GIT binary patch delta 7949 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 YWC3bSfNCL79ssEUO}~OPz&s%V0PEHQv;Y7A delta 5914 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 Q?4V-^jFUm)NEogh09-lt*Z=?k diff --git a/pkg/ebpf/bpf_bpfel.go b/pkg/ebpf/bpf_bpfel.go index 4b4c5794..9c2253d6 100644 --- a/pkg/ebpf/bpf_bpfel.go +++ b/pkg/ebpf/bpf_bpfel.go @@ -56,6 +56,8 @@ type bpfSpecs struct { type bpfProgramSpecs struct { EgressFlowParse *ebpf.ProgramSpec `ebpf:"egress_flow_parse"` IngressFlowParse *ebpf.ProgramSpec `ebpf:"ingress_flow_parse"` + PanoEgressParse *ebpf.ProgramSpec `ebpf:"pano_egress_parse"` + PanoIngressParse *ebpf.ProgramSpec `ebpf:"pano_ingress_parse"` } // bpfMapSpecs contains maps before they are loaded into the kernel. @@ -64,6 +66,7 @@ type bpfProgramSpecs struct { type bpfMapSpecs struct { AggregatedFlows *ebpf.MapSpec `ebpf:"aggregated_flows"` DirectFlows *ebpf.MapSpec `ebpf:"direct_flows"` + PacketPayloads *ebpf.MapSpec `ebpf:"packet_payloads"` } // bpfObjects contains all objects after they have been loaded into the kernel. @@ -87,12 +90,14 @@ func (o *bpfObjects) Close() error { type bpfMaps struct { AggregatedFlows *ebpf.Map `ebpf:"aggregated_flows"` DirectFlows *ebpf.Map `ebpf:"direct_flows"` + PacketPayloads *ebpf.Map `ebpf:"packet_payloads"` } func (m *bpfMaps) Close() error { return _BpfClose( m.AggregatedFlows, m.DirectFlows, + m.PacketPayloads, ) } @@ -102,12 +107,16 @@ func (m *bpfMaps) Close() error { type bpfPrograms struct { EgressFlowParse *ebpf.Program `ebpf:"egress_flow_parse"` IngressFlowParse *ebpf.Program `ebpf:"ingress_flow_parse"` + PanoEgressParse *ebpf.Program `ebpf:"pano_egress_parse"` + PanoIngressParse *ebpf.Program `ebpf:"pano_ingress_parse"` } func (p *bpfPrograms) Close() error { return _BpfClose( p.EgressFlowParse, p.IngressFlowParse, + p.PanoEgressParse, + p.PanoIngressParse, ) } diff --git a/pkg/ebpf/bpf_bpfel.o b/pkg/ebpf/bpf_bpfel.o index b28228617135f0ee03e3b7426a289ba71b98b12f..8ac6a4873d01a5713e1b2584cb49bceb20368bb2 100644 GIT binary patch delta 7720 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 E0Q~y~F8}}l delta 5637 zcmaDblkr0b;{*+H0|y2;fG`~x1Q`T2+P~#t6x^)K%g)HCIoXu2ozZ^tUcP4b$qC{f zlMN);CvOv<I5|OrhwBPE0|N+0@J%k0*f)8GBu_mL0|SFO#83`i1_lOu1_lN$1_l-j z1_lOC1_lN`h#W&00|SE~0|SEq0|P?>0|SEy0|SEu0|P?_l<mR5z)--zz#z)Nz)-=! zz)%il|6pKXsDqkQ!N|bS4rO;RGB8YFU<d;nI)jmcVKD;(gB$|`!vaPIhBXjNIrteE z7&buJAd9y_*o;h2ha83QIfNJ(7*0Uh!VC-yXD3%mNy~zq%fi6Gz{bG9aGQaFfsuiM z1!T$-1_lPP$s47FWnVEcFo;9+F??oVV335e|1vNz$WDGJCF}_@8Ds`XA3Gyh8tf`C zi-Ca|M1z6>q=p0JHK-bCkoTc%83qOh>B+Xz()Cgd3=ANZAglqE1*rs?!oa}5q`<(y zpaT_GWME*hWMp7qWnf^DWnf_NV1$GZNNoTk1A`I+0|Q8X7?cf)luRgl0Rsa=6(c0V z9xyO4G(gN0;!tK_U}%AGI8+!I7`i6El$NjO1ewXez_5^!fq|QWfdQ1XmNGIh$b+;p zFfgo!=-^X@1R_*51Cs^=1H&GOl`IDs7#NN*GBCira|+4^Iq@=-4Knuzlnrw3GYGq$ zp@D&c;XQ=I0CM{uC>vxbD-*;}kUs>VY*186LfHz83=Eo3wgV#rgCUfiz{tR0#l*m% z3GxIZ1A{G8T!D#!!3oNCU}9kKWvYi*kif*i5CoNIU}9j1hO!qhF)$=U*$0>y7_y-3 z2TTkMrBF5~A=EQ5Fld1yg_(h&3(8)=%)l@Osz!l@fdOO|D1;nX7#LPV#S`j5$$^1^ zK^x>!76yi`ObiU5h&sT+z_16Z2$T$tLfHzekQmSfMHMRp!#SvU11kf=btVP|P?}x9 z%E0g#W)4(612nyY900NsCOr9#EJr;|5F`OI9+dJx3Hl8a1A`7o0D+mjp=_9%Z%hmf zdQdSa#pDBJFfuUkg0kyRCI$v|1_p+|OyG>jqYss5g2>l1z!bm=nlNzQV&E}^DnvJ^ zk{4o-F;pH@ZkZw2oS?E~H>gBoVBj-FO}Jc^Na{eP#1Y<lum~Th)Pp2;FrNz~31&fq z&KjD5L8azpsNptH!*4<Oj3E6SV7GyFg1un})dvdQ`w(?}ppq7(7OYBxfq@I82+V<6 z<_OgUDqmheH93JwB~h4+7$`uYGA<yQdYBBz$0Crjo6ikus5T!10}}%Ss8D49MJ-4e zRIaIk7|`O}kPlp5g4IB)1#pRF1yuubuq~7g3Iu0pwE%LXD+7ZyIJ<$I<qoY&Kn}6w z0|y7#P*52F(hmv=M~DO2L41F{$=?(lH%BW5Gm7Qp=cOxviPF5{%=Em}6ot&ZlFbK{ z%o#OGic1o63*t*E3sM;}${{?4w4D6%`0UimVus>uhT`lbhRnRl3-m=ME2t<;-l}?J za+ZqGWCs<k&6R2moRirMTI=V(W&{_WAe&7X7#Kj<hK+%t0902nFo1(cfEny+kP-$1 z1_p*?B)$;?14B0?0fOa0`awYn(gRBEAVFzn1_pg*1_quj%-~uR#%JBaTn{!Z4x|cH zH!w3WWP*}O1ruE1dS(U&&ITq1P!S8#2;z%3Fo7Kc<4ZR%F@O>*jBnh)1TMN^e2{zq z)O?VB!v-dB6)nwN&%gi@09gPkdO;dKGczz~_AoJYKsBhcFfgc2U;@?A3?O-b76t~1 zIZWW<8N{z*VPFsyU;<aqFg~XM6T=Ru{?#lD46HIt3=*KCoSA{)DTuGY!~kjoNY^tn zFetJzFi5B{F|2?p0P)3Cm>4!d`N6CV44gVl3<se6YE}jY5gtZ{3rKuU9!7=-Q2r`b zkcEs4AE5j<Aie@40|%&dWM*K1$wx3TFw}!w3{$WIsz8s8fq_+pk>LlF-vQ!lFfw>B zGk`<j5gP-8k`5z70F=+m&cGmK!pM*S<tu~u28;{^P(Db#j1D711(a{e&cMKG!N}0T z%uo+DFqEBvLDGehVFpwIh|lZ7$gl#+2m5#mBf}0PKIarhh67N3H#-A^*b+ttP(1<i z&~gxe1tY@&R)~WSvokO#tzl%i0Of-nyoHhB0V}A+V`g9gyLba5!w0AWkOrAGj0``Z z{I?(%?_gx$V1pP4a-if9Mg|EaKJO7m1_LOcgM)#AGlYpDfgPgWnS+5rGJ%ny0Ey3= zz{pTh4;6rB0EPolK3Ky8MurPWeBK9)3^$;Bn0g5ghy^gd2b5pQ!N4G~fr%ji%Ad)> zz#z1Ri6H^X2gwU=U}C5*fC|72sDSdfb1*Qd9ARRZ0OhlDGB9wSU}Bg7<!f>>Fesj3 zVt4`N`*Sid$X{S$n868g5L_P0hspnd@~b!*7-SzX)iXqJK{S9As9#`WNI>F)49tM? zH*zvCXkB4qFyMx$hZ?}(0Of=9gVeu(@?r8CJP7r?511GXp!`>y3=9TO>X{fOKm|0p z7#Ku8Ffkl}@|(CA7<j)hG2B4n%Y0#Ccmd_F0m<_)Gbr#vEO^Srz@R9@%%B0~vvV^r zNUAV17(n?j`2|qE3O56TNWB9y!wINB1vdi&uM0E71t@<4Hv@xU3^N0$#sj5l82<xQ zeiKMOftf*q58{Bg+zbqIIm`?SNPL+bW(Ex?Ux0^!LAijLAppwH<6&T^7c60Bh=2-o z@-Q%nRxmRZpz$l9{PiID8fJzCP(C{^1A|l#Gedze!~rV23=HxUm>C|3Lij$s3=F(e zm>GUR`Q@N`Vg)m}zJS&ZGT{6_m6w5m=LDj10P$H*Fi%#LP-JFiV4SQdAv*btg-CrZ zsA~Xf^1@OpsD5Q&V9*0q#te+$?iNf6M4LjzK@I@%Vb~Qa4k}+@VjvpQuVG}+fL4AW zF%bR$A{ZF!!TA}?h7#YwG$R8j+ku%-q8n;K1-M3s3WB<IP;pQ;M~E^o@I%Ex*&A6r z2PzKA=8y(FR8|cp0crC<MHv`uA>xz$t;FkDz&%Qk6sS!CqW^;k21am-0W+aQ2_vY2 zX8|`^Ktj-9Wk`XT299u$I1Kwj)q@&tATdzW21J7}GpGjuVoX+-;Gg`&LPUNc1E?hq zjc`!603-|Qa)Db+ER*xC#U<Im^*u-e=GHu@?0jo+PegQpnie2cTfk<5nhGEur2hwE ziG%xkETB#Th|2(KnSmI`z^1WI7PpbD2iX8B=0M^g4}$u-GoT7#d{7|(lLz%xL75)L z2ZatO6T|o*{h&Mx<Ac<L@+gcCQV+_5P`(nlX9&u3Pyq&z22dV@@x>;8wNb7Qfu<c$ z`w-M80o5fS6(ByyN?6(g1p>%REl~9!KFGugNPJMYc@7dE<fIj7{4J<_K87<;0g#1q zlaJcU*MmX_)|~-~f`&Li-B*~iKyeHj`atG`no%%5NdF8F2il$o@mHYnLCq$R5XgLx zJajYz)b_3iXZ;%>StJ8qpz%TDEFdA60URJxkko_PVaW2(;RlcfVDl}|)Psf_AnNNu zxrBis0!={%8XwfKgJ^)L2MzEb^Fd=g$b3+{51GFM&AbyZz6-Q}1sXX(*6;$R04o0j zjSp)0!PRe`Y9Gv^1#8}e0tpn04bUtG<I5?_E2=6f2nvf%Uh3*UnbnPdvWlDh<X|_I z$t`ZGlh3*7h8f0NGWa+-8O9qzX(J0LA4Z!qWEPlY=9xi-p|p`Hgl`0)jG?p<gq|Ge zF2`dSZ)^yWH8h;8Zy>=AvBzMtqJ;fq0}0m23LXxV7kDTzDoj4;A<q~$d7-BS2PjR0 zN*9oj;(cgPfKnvL>oD8^RaG+ipqD)3@yUwb;!Iz}CjatMW6S_?IDbGDXn>4id_DQ0 zx45VRbY#p0DhD=f@<VUo$q&3GL{mVc4-5<p6QDr|mu0;Us;(w0N(k%zfcDK_K-~i> z#z2O`I-j8Y3(^OQI8LyR2hbiobkL6hG%^K}h3Np90MY>(fq>|k0PUs1WI#GV)}iZ& zVqjo^=vaV72dMNw*YO;#V*^yj1d!DrQ3eJEP$_|~12lF9wnNha)GuRTU<iPQ4#-s? r)gTNq1m@bwlM{W!IVV7S{#=t8z2#ZYgT`q<p}{!|Dn5BKqlY{I{!j-K -- GitLab