@@ -198,7 +198,7 @@ pub enum EncOpts {
198
198
Geneve ( Vec < GeneveEncOpts > ) ,
199
199
Vxlan ( Vec < VxlanEncOpts > ) ,
200
200
Erspan ( Vec < ErspanEncOpts > ) ,
201
- // Gtp(Vec<u8 >), // TODO: I don't know what this is well enough to
201
+ Gtp ( Vec < GtpEncOpts > ) , // TODO: I don't know what this is well enough to
202
202
// implement it confidently.
203
203
Other ( DefaultNla ) ,
204
204
}
@@ -209,7 +209,7 @@ impl Nla for EncOpts {
209
209
Self :: Geneve ( opts) => opts. as_slice ( ) . buffer_len ( ) ,
210
210
Self :: Vxlan ( opts) => opts. as_slice ( ) . buffer_len ( ) ,
211
211
Self :: Erspan ( opts) => opts. as_slice ( ) . buffer_len ( ) ,
212
- // Self::Gtp(v ) => v.len (),
212
+ Self :: Gtp ( opts ) => opts . as_slice ( ) . buffer_len ( ) ,
213
213
Self :: Other ( nla) => nla. value_len ( ) ,
214
214
}
215
215
}
@@ -219,7 +219,7 @@ impl Nla for EncOpts {
219
219
Self :: Geneve ( _) => TCA_FLOWER_KEY_ENC_OPTS_GENEVE ,
220
220
Self :: Vxlan ( _) => TCA_FLOWER_KEY_ENC_OPTS_VXLAN ,
221
221
Self :: Erspan ( _) => TCA_FLOWER_KEY_ENC_OPTS_ERSPAN ,
222
- // Self::Gtp(_) => TCA_FLOWER_KEY_ENC_OPTS_GTP,
222
+ Self :: Gtp ( _) => TCA_FLOWER_KEY_ENC_OPTS_GTP ,
223
223
Self :: Other ( nla) => nla. kind ( ) ,
224
224
}
225
225
}
@@ -229,7 +229,7 @@ impl Nla for EncOpts {
229
229
Self :: Geneve ( opts) => opts. as_slice ( ) . emit ( buffer) ,
230
230
Self :: Vxlan ( opts) => opts. as_slice ( ) . emit ( buffer) ,
231
231
Self :: Erspan ( opts) => opts. as_slice ( ) . emit ( buffer) ,
232
- // Self::Gtp(v ) => buffer.copy_from_slice(v ),
232
+ Self :: Gtp ( opts ) => opts . as_slice ( ) . emit ( buffer ) ,
233
233
Self :: Other ( nla) => nla. emit_value ( buffer) ,
234
234
}
235
235
}
@@ -2612,3 +2612,64 @@ impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for CfmAttribute {
2612
2612
} )
2613
2613
}
2614
2614
}
2615
+
2616
+ const TCA_FLOWER_KEY_ENC_OPT_GTP_PDU_TYPE : u16 = 1 ; /* u8 */
2617
+ const TCA_FLOWER_KEY_ENC_OPT_GTP_QFI : u16 = 2 ; /* u8 */
2618
+
2619
+ /// I don't have any real experience with GTP.
2620
+ /// It looks like the [spec for GTP `PduType`][1] is available
2621
+ /// but the number of codes is fairly large, and I am not sure
2622
+ /// more than `u8` is justified.
2623
+ /// I can implement all of those codes as an enum if needed.
2624
+ ///
2625
+ /// [1]: https://www.etsi.org/deliver/etsi_ts/129000_129099/129060/12.06.00_60/ts_129060v120600p.pdf#page=22
2626
+ #[ derive( Debug , PartialEq , Eq , Clone ) ]
2627
+ #[ non_exhaustive]
2628
+ pub enum GtpEncOpts {
2629
+ PduType ( u8 ) ,
2630
+ Qfi ( u8 ) ,
2631
+ Other ( DefaultNla ) ,
2632
+ }
2633
+
2634
+ impl Nla for GtpEncOpts {
2635
+ fn value_len ( & self ) -> usize {
2636
+ 1
2637
+ }
2638
+
2639
+ fn kind ( & self ) -> u16 {
2640
+ match self {
2641
+ GtpEncOpts :: PduType ( _) => TCA_FLOWER_KEY_ENC_OPT_GTP_PDU_TYPE ,
2642
+ GtpEncOpts :: Qfi ( _) => TCA_FLOWER_KEY_ENC_OPT_GTP_QFI ,
2643
+ GtpEncOpts :: Other ( nla) => nla. kind ( ) ,
2644
+ }
2645
+ }
2646
+
2647
+ fn emit_value ( & self , buffer : & mut [ u8 ] ) {
2648
+ match self {
2649
+ GtpEncOpts :: PduType ( pdu_type) => {
2650
+ buffer[ 0 ] = * pdu_type;
2651
+ }
2652
+ GtpEncOpts :: Qfi ( qfi) => {
2653
+ buffer[ 0 ] = * qfi;
2654
+ }
2655
+ GtpEncOpts :: Other ( nla) => nla. emit_value ( buffer) ,
2656
+ }
2657
+ }
2658
+ }
2659
+
2660
+ impl < ' a , T : AsRef < [ u8 ] > + ?Sized > Parseable < NlaBuffer < & ' a T > > for GtpEncOpts {
2661
+ fn parse ( buf : & NlaBuffer < & ' a T > ) -> Result < Self , DecodeError > {
2662
+ let payload = buf. value ( ) ;
2663
+ Ok ( match buf. kind ( ) {
2664
+ TCA_FLOWER_KEY_ENC_OPT_GTP_PDU_TYPE => {
2665
+ GtpEncOpts :: PduType ( parse_u8 ( payload) ?)
2666
+ }
2667
+ TCA_FLOWER_KEY_ENC_OPT_GTP_QFI => {
2668
+ GtpEncOpts :: Qfi ( parse_u8 ( payload) ?)
2669
+ }
2670
+ _ => GtpEncOpts :: Other (
2671
+ DefaultNla :: parse ( buf) . context ( "failed to parse gtp nla" ) ?,
2672
+ ) ,
2673
+ } )
2674
+ }
2675
+ }
0 commit comments