1use core::hash::Hash;
2use core::str::FromStr;
3use std::cmp;
4use std::fmt::{self, Debug};
5
6
7use crate::typeenum; #[cfg(feature = "serde")]
10use serde::{Serialize, Deserialize};
11
12use inetnum::addr::Prefix;
21use super::common::{compose_len_prefix, compose_prefix, parse_v4_prefix, parse_v6_prefix};
22use super::common::{PathId, prefix_bits_to_bytes};
23use crate::util::parser::ParseError;
24use paste::paste;
25
26
27use octseq::{Octets, OctetsBuilder, Parser};
28
29use super::evpn::*;
30use super::flowspec::*;
31use super::mpls::*;
32use super::mpls_vpn::*;
33use super::routetarget::*;
34use super::vpls::*;
35
36macro_rules! addpath {
46 ($nlri:ident ) => { paste! {
47 #[derive(Copy, Clone, Debug, Hash, PartialEq, Ord, PartialOrd)]
48 #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
49 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
50 pub struct [<$nlri AddpathNlri>](PathId, [<$nlri Nlri>]);
51 impl AfiSafiNlri for [<$nlri AddpathNlri>] {
52 type Nlri = <[<$nlri Nlri>] as AfiSafiNlri>::Nlri;
53 fn nlri(&self) -> &Self::Nlri {
54 &self.1.nlri()
55 }
56 }
57
58 addpath!(@generic $nlri);
59
60 }};
61
62 ($nlri:ident <$gen:ident>) => { paste! {
63 #[allow(clippy::derived_hash_with_manual_eq)]
64 #[derive(Clone, Debug, Hash)]
65 #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
66 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
67 pub struct [<$nlri AddpathNlri>]<$gen>(PathId, [<$nlri Nlri>]<$gen>);
68 impl<$gen> AfiSafiNlri for [<$nlri AddpathNlri>]<$gen> {
69 type Nlri = <[<$nlri Nlri>]<$gen> as AfiSafiNlri>::Nlri;
70 fn nlri(&self) -> &Self::Nlri {
71 &self.1.nlri()
72 }
73 }
74
75 impl<$gen: AsRef<[u8]>> Ord for [<$nlri AddpathNlri>]<$gen> {
76 fn cmp(&self, other: &Self) -> cmp::Ordering {
77 self.1.cmp(&other.1).then(self.0.cmp(&other.0))
78 }
79 }
80 impl<$gen: AsRef<[u8]>> PartialOrd for [<$nlri AddpathNlri>]<$gen> {
81 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
82 Some(self.cmp(&other))
83 }
84 }
85
86 addpath!(@generic $nlri<$gen>);
87
88 }};
89
90 (@generic $nlri:ident $(<$gen:ident>)?) => { paste! {
91
92 impl$(<$gen>)? AfiSafi for [<$nlri AddpathNlri>]$(<$gen>)? {
93 fn afi() -> Afi { <[<$nlri Nlri>]$(<$gen>)? as AfiSafi>::afi() }
94 fn afi_safi() -> AfiSafiType { <[<$nlri Nlri>]$(<$gen>)? as AfiSafi>::afi_safi() }
95 }
96
97 impl<'a, Octs, P> NlriParse<'a, Octs, P> for [<$nlri AddpathNlri>]$(<$gen>)?
98 where
99 Octs: Octets,
100 P: 'a + Octets<Range<'a> = Octs>
101 {
102 type Output = Self;
103 fn parse(parser: &mut Parser<'a, P>) -> Result<Self::Output, ParseError> {
104 let path_id = PathId(parser.parse_u32_be()?);
105 let inner = [<$nlri Nlri>]::parse(parser)?;
106 Ok(
107 Self(path_id, inner)
108 )
109 }
110 }
111
112 impl$(<$gen>)? NlriCompose for [<$nlri AddpathNlri>]$(<$gen>)?
113 $(where
114 $gen: AsRef<[u8]>
115 )?
116 {
117 fn compose<Target: OctetsBuilder>(&self, target: &mut Target)
118 -> Result<(), Target::AppendError>
119 {
120 target.append_slice(&self.0.0.to_be_bytes())?;
121 self.1.compose(target)
122 }
123
124 fn compose_len(&self) -> usize {
125 4 + self.1.compose_len()
126 }
127 }
128
129 impl$(<$gen>)? IsNlri for [<$nlri AddpathNlri>]$(<$gen>)? {
130 fn nlri_type() -> NlriType {
131 NlriType::[<$nlri Addpath>]
132 }
133 }
134
135 impl$(<$gen>)? Addpath for [<$nlri AddpathNlri>]$(<$gen>)? {
136 fn path_id(&self) -> PathId {
137 self.0
138 }
139 }
140
141 impl$(<$gen: AsRef<[u8]>>)? Eq for [<$nlri AddpathNlri>]$(<$gen>)? { }
142
143 impl$(<$gen>)? fmt::Display for [<$nlri AddpathNlri>]$(<$gen>)? {
144 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
145 write!(f, "[{}] ", self.0)?;
146 fmt::Display::fmt(&self.1, f)
147 }
148 }
149 }};
150}
151
152macro_rules! afisafi {
155 (
156 $(
157 $afi_code:expr => $afi_name:ident [ $( $safi_code:expr => $safi_name:ident$(<$gen:ident>)? ),+ $(,)* ]
158 ),+ $(,)*
159 ) =>
160{
161 typeenum!(
162 #[cfg_attr(feature = "serde", serde(from = "u16"))]
164 Afi, u16,
165 {
166 $($afi_code => $afi_name),+
167 });
168
169paste! {
170 #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
171 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
172 #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
173 pub enum AfiSafiType {
174 $( $( [<$afi_name $safi_name>] ,)+)+
175 Unsupported(u16, u8),
176 }
177
178 impl From<(u16, u8)> for AfiSafiType {
179 fn from(t: (u16, u8)) -> Self {
180 match t {
181 $($(
182 ($afi_code, $safi_code) => Self::[<$afi_name $safi_name>],
183 )+)+
184 _ => Self::Unsupported(t.0, t.1)
185 }
186 }
187 }
188
189 impl From<AfiSafiType> for (u16, u8) {
190 fn from(afisafi: AfiSafiType) -> (u16, u8) {
191 match afisafi {
192 $($(
193 AfiSafiType::[<$afi_name $safi_name>] => ($afi_code, $safi_code),
194 )+)+
195 AfiSafiType::Unsupported(a, s) => (a, s)
196 }
197 }
198 }
199
200 impl AfiSafiType {
201 pub const fn afi(self) -> Afi {
202 match self {
203 $($(
204 Self::[<$afi_name $safi_name>] => Afi::$afi_name,
205 )+)+
206 Self::Unsupported(a, _s) => Afi::Unimplemented(a)
207 }
208 }
209
210 pub const fn as_bytes(self) -> [u8; 3] {
211 match self {
212 $($(
213 Self::[<$afi_name $safi_name>] => {
214 let afi = $afi_code.to_be_bytes();
215 [afi[0], afi[1], $safi_code]
216 }
217 )+)+
218 AfiSafiType::Unsupported(a, s) => {
219 let afi = a.to_be_bytes();
220 [afi[0], afi[1], s]
221 }
222 }
223 }
224 }
225
226
227 impl fmt::Display for AfiSafiType {
228 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
229 match self {
230 $($(
231 Self::[<$afi_name $safi_name>] => {
232 write!(f, stringify!([<$afi_name $safi_name>]))
233 }
234 )+)+
235 Self::Unsupported(a, s) => {
236 write!(f, "UnsupportedAfiSafi({}, {})", a, s)
237 }
238 }
239 }
240 }
241
242 #[derive(Clone, Debug, Hash)]
244 #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
245 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
246 pub enum Nlri<Octs> {
247 $($(
248 [<$afi_name $safi_name>]([<$afi_name $safi_name Nlri>]$(<$gen>)?),
249 [<$afi_name $safi_name Addpath>]([<$afi_name $safi_name AddpathNlri>]$(<$gen>)?)
250 ,)+)+
251 }
252
253 impl<Octs> Nlri<Octs> {
254 pub const fn afi_safi(&self) -> AfiSafiType {
255 match self {
256 $($(
257 Self::[<$afi_name $safi_name>](..) => AfiSafiType::[<$afi_name $safi_name >],
258 Self::[<$afi_name $safi_name Addpath>](..) => AfiSafiType::[<$afi_name $safi_name >],
259 )+)+
260 }
261 }
262
263 pub const fn nlri_type(&self) -> NlriType {
264 match self {
265 $($(
266 Self::[<$afi_name $safi_name>](..) => NlriType::[<$afi_name $safi_name >],
267 Self::[<$afi_name $safi_name Addpath>](..) => NlriType::[<$afi_name $safi_name Addpath>],
268 )+)+
269 }
270 }
271 }
272
273 impl<Octs> Nlri<Octs>
274 where
275 Octs: AsRef<[u8]>
276 {
277 pub fn compose<Target: OctetsBuilder>(&self, target: &mut Target)
278 -> Result<(), Target::AppendError> {
279 match self {
280 $($(
281 Nlri::[<$afi_name $safi_name>](n) => n.compose(target),
282 Nlri::[<$afi_name $safi_name Addpath>](n) => n.compose(target),
283 )+)+
284 }
285 }
286 }
287
288
289 impl<Octs, Other> PartialEq<Nlri<Other>> for Nlri<Octs>
290 where Octs: AsRef<[u8]>,
291 Other: AsRef<[u8]>
292 {
293 fn eq(&self, other: &Nlri<Other>) -> bool {
294 match (self, other) {
295 $($(
296 (Nlri::[<$afi_name $safi_name>](p1), Nlri::[<$afi_name $safi_name>](p2)) => p1 == p2,
297 (Nlri::[<$afi_name $safi_name Addpath>](p1), Nlri::[<$afi_name $safi_name Addpath>](p2)) => p1 == p2,
298 )+)+
299 _ => false
300 }
301 }
302 }
303
304 impl<Octs> Ord for Nlri<Octs>
305 where Octs: AsRef<[u8]>
306 {
307 fn cmp(&self, other: &Nlri<Octs>) -> cmp::Ordering {
308 match (self, other) {
309 $($(
310 (Nlri::[<$afi_name $safi_name>](p1), Nlri::[<$afi_name $safi_name>](p2)) => p1.cmp(p2),
311 (Nlri::[<$afi_name $safi_name Addpath>](p1), Nlri::[<$afi_name $safi_name Addpath>](p2)) => p1.cmp(p2),
312 )+)+
313 (a, b) => a.nlri_type().cmp(&b.nlri_type()),
314 }
315 }
316 }
317
318 impl<T> fmt::Display for Nlri<T> {
319 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
320 match self {
321 $($(
322 Self::[<$afi_name $safi_name>](i) => fmt::Display::fmt(i, f),
323 Self::[<$afi_name $safi_name Addpath>](i) => {
324 fmt::Display::fmt(i, f)
325 }
326 )+)+
327 }
328 }
329 }
330
331 #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
332 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
333 #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
334 pub enum NlriType {
335 $($(
336 [<$afi_name $safi_name>],
337 [<$afi_name $safi_name Addpath>],
338 )+)+
339 Unsupported(u16, u8),
340 }
341
342 impl NlriType {
343 pub const fn afi_safi(&self) -> AfiSafiType {
344 match self {
345 $($(
346 Self::[<$afi_name $safi_name>] => AfiSafiType::[<$afi_name $safi_name >],
347 Self::[<$afi_name $safi_name Addpath>] => AfiSafiType::[<$afi_name $safi_name >],
348 )+)+
349 Self::Unsupported(a, s) => AfiSafiType::Unsupported(*a, *s)
350 }
351 }
352 }
353
354
355 impl From<(AfiSafiType, bool)> for NlriType {
356 fn from(t: (AfiSafiType, bool)) -> Self {
357 match (t.0, t.1) {
358 $($(
359 (AfiSafiType::[<$afi_name $safi_name>], false) => NlriType::[<$afi_name $safi_name >],
360 (AfiSafiType::[<$afi_name $safi_name>], true) => NlriType::[<$afi_name $safi_name Addpath>],
361 )+)+
362 (AfiSafiType::Unsupported(a, s), _) => NlriType::Unsupported(a, s),
363 }
364 }
365 }
366
367 impl From<NlriType> for AfiSafiType {
368 fn from(n: NlriType) -> Self {
369 n.afi_safi()
370 }
371 }
372
373
374$($(
375 impl$(<$gen>)? AfiSafi for [<$afi_name $safi_name Nlri>]$(<$gen>)? {
382 fn afi() -> Afi { Afi::$afi_name }
383 fn afi_safi() -> AfiSafiType {
384 AfiSafiType::[<$afi_name $safi_name>]
385 }
386 }
387
388 impl$(<$gen>)? IsNlri for [<$afi_name $safi_name Nlri>]$(<$gen>)? {
389 fn nlri_type() -> NlriType {
390 NlriType::[<$afi_name $safi_name>]
391 }
392 }
393
394 impl$(<$gen>)? fmt::Display for [<$afi_name $safi_name Nlri>]$(<$gen>)?
395 where <[<$afi_name $safi_name Nlri>]$(<$gen>)? as AfiSafiNlri>::Nlri: fmt::Display {
396 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
397 write!(f, "{}", self.nlri())
398 }
399 }
400
401 impl<Octs> From<[<$afi_name $safi_name Nlri>]$(<$gen>)?> for Nlri<Octs> {
402 fn from(n: [<$afi_name $safi_name Nlri>]$(<$gen>)?) -> Self {
403 Nlri::[<$afi_name $safi_name>](n)
404 }
405 }
406
407 impl<Octs> From<[<$afi_name $safi_name AddpathNlri>]$(<$gen>)?> for Nlri<Octs> {
408 fn from(n: [<$afi_name $safi_name AddpathNlri>]$(<$gen>)?) -> Self {
409 Nlri::[<$afi_name $safi_name Addpath>](n)
410 }
411 }
412
413 impl$(<$gen>)? From<[<$afi_name $safi_name AddpathNlri>]$(<$gen>)?> for [<$afi_name $safi_name Nlri>]$(<$gen>)? {
414 fn from(n: [<$afi_name $safi_name AddpathNlri>]$(<$gen>)?) -> Self {
415 n.1
416 }
417 }
418
419 impl$(<$gen: AsRef<[u8]>>)? Eq for [<$afi_name $safi_name Nlri>]$(<$gen>)? { }
420
421 impl<'a, Octs, P> NlriIter<'a, Octs, P, [<$afi_name $safi_name Nlri>]$(<$gen>)?>
424 where
425 Octs: Octets,
426 P: Octets<Range<'a> = Octs>
427 {
428 pub const fn [<$afi_name:lower _ $safi_name:lower>](parser: Parser<'a, P>) -> Self {
429 NlriIter::<'a, Octs, P, [<$afi_name $safi_name Nlri>]$(<$gen>)?>::new(parser)
430 }
431 }
432
433 impl<'a, Octs, P> NlriIter<'a, Octs, P, [<$afi_name $safi_name AddpathNlri>]$(<$gen>)?>
434 where
435 Octs: Octets,
436 P: Octets<Range<'a> = Octs>
437 {
438 pub const fn [<$afi_name:lower _ $safi_name:lower _ addpath>](parser: Parser<'a, P>) -> Self {
439 NlriIter::<'a, Octs, P, [<$afi_name $safi_name AddpathNlri>]$(<$gen>)?>::new(parser)
440 }
441 }
442
443 impl$(<$gen>)? [<$afi_name $safi_name Nlri>]$(<$gen>)? {
476 pub const fn into_addpath(self, path_id: PathId) -> [<$afi_name $safi_name AddpathNlri>]$(<$gen>)? {
477 [<$afi_name $safi_name AddpathNlri>](path_id, self)
478 }
479 }
480
481 addpath!([<$afi_name $safi_name>]$(<$gen>)?);
483)+)+
484
485}}
486}
487
488impl<Octs: AsRef<[u8]>> Eq for Nlri<Octs> {}
491
492impl<Octs> PartialOrd for Nlri<Octs>
493where Octs: AsRef<[u8]>,
494{
495 fn partial_cmp(&self, other: &Nlri<Octs>) -> Option<cmp::Ordering> {
496 Some(self.cmp(other))
497 }
498}
499
500
501impl Nlri<&[u8]> {
505 pub fn unicast_from_str(prefix: &str)
510 -> Result<Nlri<&[u8]>, <Prefix as FromStr>::Err>
511 {
512 let p = Prefix::from_str(prefix)?;
513 if p.is_v4() {
514 Ok(Nlri::Ipv4Unicast(Ipv4UnicastNlri(p)))
515 } else {
516 Ok(Nlri::Ipv6Unicast(Ipv6UnicastNlri(p)))
517 }
518 }
519}
520
521pub trait AfiSafi {
525 fn afi() -> Afi;
526 fn afi_safi() -> AfiSafiType;
527}
528
529pub trait IsNlri {
530 fn nlri_type() -> NlriType;
531}
532
533pub trait AfiSafiNlri: AfiSafi + IsNlri { type Nlri;
536 fn nlri(&self) -> &Self::Nlri;
537
538 }
541
542pub trait NlriParse<'a, O, P>: Sized + IsNlri
543 where P: 'a + Octets<Range<'a> = O>
544{
545 type Output: AfiSafi;
546 fn parse(parser: &mut Parser<'a, P>) -> Result<Self::Output, ParseError>;
547}
548
549pub trait NlriCompose: AfiSafiNlri {
550 fn compose<Target: OctetsBuilder>(&self, target: &mut Target)
551 -> Result<(), Target::AppendError>;
552
553 fn compose_len(&self) -> usize;
554}
555
556
557pub trait IsPrefix: AfiSafiNlri {
559 fn prefix(&self) -> Prefix;
560
561 fn path_id(&self) -> Option<PathId> {
562 None
563 }
564}
565
566macro_rules! is_prefix {
576 ($nlri:ident) => { paste! {
577 impl IsPrefix for [<$nlri Nlri>] {
578 fn prefix(&self) -> Prefix {
579 (*self.nlri()).into()
580 }
581 }
582 impl IsPrefix for [<$nlri AddpathNlri>] {
583 fn prefix(&self) -> Prefix {
584 (*self.nlri()).into()
585 }
586 fn path_id(&self) -> Option<PathId> {
587 Some(<Self as Addpath>::path_id(&self))
588 }
589 }
590 }}
591}
592is_prefix!(Ipv4Unicast);
593is_prefix!(Ipv4Multicast);
594is_prefix!(Ipv6Unicast);
595is_prefix!(Ipv6Multicast);
596
597pub trait Addpath: AfiSafiNlri {
599 fn path_id(&self) -> PathId;
600}
601
602
603afisafi! {
610 1_u16 => Ipv4 [
611 1 => Unicast,
612 2 => Multicast,
613 4 => MplsUnicast<Octs>,
614 128 => MplsVpnUnicast<Octs>,
615 132 => RouteTarget<Octs>,
616 133 => FlowSpec<Octs>,
617 ],
620 2_u16 => Ipv6 [
621 1 => Unicast,
622 2 => Multicast,
623 4 => MplsUnicast<Octs>,
624 128 => MplsVpnUnicast<Octs>,
625 133 => FlowSpec<Octs>,
626 ],
628 25_u16 => L2Vpn [
629 65 => Vpls,
630 70 => Evpn<Octs>,
631 ]
632}
633
634
635#[derive(Copy, Clone, Debug, Hash, PartialEq, Ord, PartialOrd)]
641#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
642#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
643pub struct Ipv4UnicastNlri(Prefix);
644
645impl AfiSafiNlri for Ipv4UnicastNlri {
646 type Nlri = Prefix;
647 fn nlri(&self) -> &Self::Nlri {
648 &self.0
649 }
650}
651
652impl FromStr for Ipv4UnicastNlri {
653 type Err = &'static str;
654 fn from_str(s: &str) -> Result<Self, Self::Err> {
655 let p = Prefix::from_str(s).map_err(|_| "could not parse prefix")?;
656 p.try_into()
657 }
658}
659
660impl TryFrom<Prefix> for Ipv4UnicastNlri {
661 type Error = &'static str;
662 fn try_from(p: Prefix) -> Result<Self, Self::Error> {
663 if p.is_v4() {
664 Ok( Self(p) )
665 } else {
666 Err("prefix is not IPv4")
667 }
668 }
669}
670
671impl TryFrom<(Prefix, PathId)> for Ipv4UnicastAddpathNlri {
672 type Error = &'static str;
673
674 fn try_from((prefix, path_id): (Prefix, PathId)) -> Result<Self, Self::Error> {
675 Ok(Ipv4UnicastNlri::try_from(prefix)?.into_addpath(path_id))
676 }
677}
678
679
680impl<'a, O, P> NlriParse<'a, O, P> for Ipv4UnicastNlri
681where
682 O: Octets,
683 P: 'a + Octets<Range<'a> = O>
684{
685 type Output = Self;
686 fn parse(parser: &mut Parser<'a, P>) -> Result<Self::Output, ParseError> {
687 Ok(
688 Self(parse_v4_prefix(parser)?)
689 )
690 }
691}
692
693impl NlriCompose for Ipv4UnicastNlri {
694 fn compose_len(&self) -> usize {
695 1 + compose_len_prefix(self.prefix())
697 }
698
699 fn compose<Target: OctetsBuilder>(&self, target: &mut Target)
700 -> Result<(), Target::AppendError>
701 {
702 compose_prefix(self.prefix(), target)
703 }
704}
705
706#[derive(Copy, Clone, Debug, Hash, PartialEq, Ord, PartialOrd)]
709#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
710#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
711pub struct Ipv4MulticastNlri(Prefix);
712
713impl AfiSafiNlri for Ipv4MulticastNlri {
714 type Nlri = Prefix;
715 fn nlri(&self) -> &Self::Nlri {
716 &self.0
717 }
718}
719
720impl FromStr for Ipv4MulticastNlri {
721 type Err = &'static str;
722 fn from_str(s: &str) -> Result<Self, Self::Err> {
723 let p = Prefix::from_str(s).map_err(|_| "err")?;
724 p.try_into()
725 }
726}
727
728impl TryFrom<Prefix> for Ipv4MulticastNlri {
729 type Error = &'static str;
730 fn try_from(p: Prefix) -> Result<Self, Self::Error> {
731 if p.is_v4() {
732 Ok( Self(p) )
733 } else {
734 Err("prefix is not IPv4")
735 }
736 }
737}
738
739impl TryFrom<(Prefix, PathId)> for Ipv4MulticastAddpathNlri {
740 type Error = &'static str;
741
742 fn try_from((prefix, path_id): (Prefix, PathId)) -> Result<Self, Self::Error> {
743 Ok(Ipv4MulticastNlri::try_from(prefix)?.into_addpath(path_id))
744 }
745}
746
747impl<'a, O, P> NlriParse<'a, O, P> for Ipv4MulticastNlri
748where
749 O: Octets,
750 P: 'a + Octets<Range<'a> = O>
751{
752 type Output = Self;
753 fn parse(parser: &mut Parser<'a, P>) -> Result<Self::Output, ParseError> {
754 Ok(
755 Self(parse_v4_prefix(parser)?)
756 )
757 }
758}
759
760impl NlriCompose for Ipv4MulticastNlri {
761 fn compose_len(&self) -> usize {
762 1 + compose_len_prefix(self.prefix())
764 }
765
766 fn compose<Target: OctetsBuilder>(&self, target: &mut Target)
767 -> Result<(), Target::AppendError>
768 {
769 compose_prefix(self.prefix(), target)
770 }
771}
772
773#[derive(Copy, Clone, Debug, Hash)]
776#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
777#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
778pub struct Ipv4MplsUnicastNlri<Octs>(MplsNlri<Octs>);
779
780impl<Octs> AfiSafiNlri for Ipv4MplsUnicastNlri<Octs> {
781 type Nlri = MplsNlri<Octs>;
782 fn nlri(&self) -> &Self::Nlri {
783 &self.0
784 }
785}
786
787impl<'a, O, P> NlriParse<'a, O, P> for Ipv4MplsUnicastNlri<O>
788where
789 O: Octets,
790 P: 'a + Octets<Range<'a> = O>
791{
792 type Output = Self;
793
794 fn parse(parser: &mut Parser<'a, P>)
795 -> Result<Self::Output, ParseError>
796 {
797 Ok(
798 Self(MplsNlri::parse(parser, Afi::Ipv4)?)
799 )
800 }
801}
802
803impl<Octs: AsRef<[u8]>> NlriCompose for Ipv4MplsUnicastNlri<Octs> {
804 fn compose_len(&self) -> usize {
805 1 + self.nlri().compose_len()
807 }
808
809 fn compose<Target: OctetsBuilder>(&self, target: &mut Target)
810 -> Result<(), Target::AppendError> {
811 self.nlri().compose(target)
812 }
813}
814
815impl<Octs, Other> PartialEq<Ipv4MplsUnicastNlri<Other>> for Ipv4MplsUnicastNlri<Octs>
816where Octs: AsRef<[u8]>,
817 Other: AsRef<[u8]>
818{
819 fn eq(&self, other: &Ipv4MplsUnicastNlri<Other>) -> bool {
820 self.0 == other.0
821 }
822}
823
824
825impl<Octs, Other> PartialEq<Ipv4MplsUnicastAddpathNlri<Other>> for Ipv4MplsUnicastAddpathNlri<Octs>
826where Octs: AsRef<[u8]>,
827 Other: AsRef<[u8]>
828{
829 fn eq(&self, other: &Ipv4MplsUnicastAddpathNlri<Other>) -> bool {
830 self.0 == other.0
831 }
832}
833
834impl<Octs> PartialOrd for Ipv4MplsUnicastNlri<Octs>
835where Octs: AsRef<[u8]>,
836{
837 fn partial_cmp(&self, other: &Ipv4MplsUnicastNlri<Octs>) -> Option<cmp::Ordering> {
838 Some(self.cmp(other))
839 }
840}
841
842impl<Octs: AsRef<[u8]>> Ord for Ipv4MplsUnicastNlri<Octs> {
843 fn cmp(&self, other: &Self) -> cmp::Ordering {
844 self.0.cmp(&other.0)
845 }
846}
847
848#[derive(Copy, Clone, Debug, Hash)]
851#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
852#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
853pub struct Ipv4MplsVpnUnicastNlri<Octs>(MplsVpnNlri<Octs>);
854
855impl<Octs> AfiSafiNlri for Ipv4MplsVpnUnicastNlri<Octs> {
856 type Nlri = MplsVpnNlri<Octs>;
857 fn nlri(&self) -> &Self::Nlri {
858 &self.0
859 }
860}
861
862impl<'a, O, P> NlriParse<'a, O, P> for Ipv4MplsVpnUnicastNlri<O>
863where
864 O: Octets,
865 P: 'a + Octets<Range<'a> = O>
866{
867 type Output = Self;
868
869 fn parse(parser: &mut Parser<'a, P>)
870 -> Result<Self::Output, ParseError>
871 {
872 let (labels, rd, prefix) =
873 parse_labels_rd_prefix(parser, Afi::Ipv4)?;
874
875 Ok(Self(MplsVpnNlri::new(prefix, labels, rd)))
876 }
877}
878
879impl<Octs: AsRef<[u8]>> NlriCompose for Ipv4MplsVpnUnicastNlri<Octs> {
880 fn compose_len(&self) -> usize {
881 1 + self.nlri().compose_len()
882 }
883
884 fn compose<Target: OctetsBuilder>(&self, target: &mut Target)
885 -> Result<(), Target::AppendError> {
886 self.nlri().compose(target)
887 }
888}
889
890impl<Octs, Other> PartialEq<Ipv4MplsVpnUnicastNlri<Other>> for Ipv4MplsVpnUnicastNlri<Octs>
891where Octs: AsRef<[u8]>,
892 Other: AsRef<[u8]>
893{
894 fn eq(&self, other: &Ipv4MplsVpnUnicastNlri<Other>) -> bool {
895 self.0 == other.0
896 }
897}
898
899impl<Octs, Other> PartialEq<Ipv4MplsVpnUnicastAddpathNlri<Other>> for Ipv4MplsVpnUnicastAddpathNlri<Octs>
900where Octs: AsRef<[u8]>,
901 Other: AsRef<[u8]>
902{
903 fn eq(&self, other: &Ipv4MplsVpnUnicastAddpathNlri<Other>) -> bool {
904 self.0 == other.0
905 }
906}
907
908impl<Octs> PartialOrd for Ipv4MplsVpnUnicastNlri<Octs>
909where Octs: AsRef<[u8]>,
910{
911 fn partial_cmp(&self, other: &Ipv4MplsVpnUnicastNlri<Octs>) -> Option<cmp::Ordering> {
912 Some(self.cmp(other))
913 }
914}
915
916impl<Octs: AsRef<[u8]>> Ord for Ipv4MplsVpnUnicastNlri<Octs> {
917 fn cmp(&self, other: &Self) -> cmp::Ordering {
918 self.0.cmp(&other.0)
919 }
920}
921
922#[derive(Clone, Debug, Hash)]
925#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
926#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
927pub struct Ipv4RouteTargetNlri<Octs>(RouteTargetNlri<Octs>);
928
929impl<Octs> AfiSafiNlri for Ipv4RouteTargetNlri<Octs> {
930 type Nlri = RouteTargetNlri<Octs>;
931 fn nlri(&self) -> &Self::Nlri {
932 &self.0
933 }
934}
935
936impl<'a, O, P> NlriParse<'a, O, P> for Ipv4RouteTargetNlri<O>
937where
938 O: Octets,
939 P: 'a + Octets<Range<'a> = O>
940{
941 type Output = Self;
942
943 fn parse(parser: &mut Parser<'a, P>)
944 -> Result<Self::Output, ParseError>
945 {
946
947 Ok(Self(RouteTargetNlri::parse(parser)?))
948 }
949}
950
951impl<Octs: AsRef<[u8]>> NlriCompose for Ipv4RouteTargetNlri<Octs> {
952 fn compose_len(&self) -> usize {
953 self.nlri().compose_len()
954 }
955
956 fn compose<Target: OctetsBuilder>(&self, target: &mut Target)
957 -> Result<(), Target::AppendError> {
958 self.nlri().compose(target)
959 }
960}
961
962impl<Octs, Other> PartialEq<Ipv4RouteTargetNlri<Other>> for Ipv4RouteTargetNlri<Octs>
963where Octs: AsRef<[u8]>,
964 Other: AsRef<[u8]>
965{
966 fn eq(&self, other: &Ipv4RouteTargetNlri<Other>) -> bool {
967 self.0 == other.0
968 }
969}
970
971impl<Octs, Other> PartialEq<Ipv4RouteTargetAddpathNlri<Other>> for Ipv4RouteTargetAddpathNlri<Octs>
972where Octs: AsRef<[u8]>,
973 Other: AsRef<[u8]>
974{
975 fn eq(&self, other: &Ipv4RouteTargetAddpathNlri<Other>) -> bool {
976 self.0 == other.0
977 }
978}
979
980impl<Octs> PartialOrd for Ipv4RouteTargetNlri<Octs>
981where Octs: AsRef<[u8]>,
982{
983 fn partial_cmp(&self, other: &Ipv4RouteTargetNlri<Octs>) -> Option<cmp::Ordering> {
984 Some(self.cmp(other))
985 }
986}
987
988impl<Octs: AsRef<[u8]>> Ord for Ipv4RouteTargetNlri<Octs> {
989 fn cmp(&self, other: &Self) -> cmp::Ordering {
990 self.0.cmp(&other.0)
991 }
992}
993
994#[derive(Clone, Debug, Hash)]
997#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
998#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
999pub struct Ipv4FlowSpecNlri<Octs>(FlowSpecNlri<Octs>);
1000
1001impl<Octs> AfiSafiNlri for Ipv4FlowSpecNlri<Octs> {
1002 type Nlri = FlowSpecNlri<Octs>;
1003 fn nlri(&self) -> &Self::Nlri {
1004 &self.0
1005 }
1006}
1007
1008impl<'a, O, P> NlriParse<'a, O, P> for Ipv4FlowSpecNlri<O>
1009where
1010 O: Octets,
1011 P: 'a + Octets<Range<'a> = O>
1012{
1013 type Output = Self;
1014
1015 fn parse(parser: &mut Parser<'a, P>)
1016 -> Result<Self::Output, ParseError>
1017 {
1018
1019 Ok(Self(FlowSpecNlri::parse(parser, Afi::Ipv4)?))
1020 }
1021}
1022
1023impl<Octs: AsRef<[u8]>> NlriCompose for Ipv4FlowSpecNlri<Octs> {
1024 fn compose_len(&self) -> usize {
1025 let len = self.nlri().compose_len();
1027 if len >= 240 {
1028 2 + len
1029 } else {
1030 1 + len
1031 }
1032 }
1033
1034 fn compose<Target: OctetsBuilder>(&self, target: &mut Target)
1035 -> Result<(), Target::AppendError> {
1036 self.nlri().compose(target)
1037 }
1038}
1039
1040impl<T> From<Ipv4FlowSpecNlri<T>> for FlowSpecNlri<T> {
1041 fn from(value: Ipv4FlowSpecNlri<T>) -> Self {
1042 value.0
1043 }
1044}
1045
1046impl<Octs, Other> PartialEq<Ipv4FlowSpecNlri<Other>> for Ipv4FlowSpecNlri<Octs>
1047where Octs: AsRef<[u8]>,
1048 Other: AsRef<[u8]>
1049{
1050 fn eq(&self, other: &Ipv4FlowSpecNlri<Other>) -> bool {
1051 self.0 == other.0
1052 }
1053}
1054
1055impl<Octs, Other> PartialEq<Ipv4FlowSpecAddpathNlri<Other>> for Ipv4FlowSpecAddpathNlri<Octs>
1056where Octs: AsRef<[u8]>,
1057 Other: AsRef<[u8]>
1058{
1059 fn eq(&self, other: &Ipv4FlowSpecAddpathNlri<Other>) -> bool {
1060 self.0 == other.0
1061 }
1062}
1063
1064impl<Octs> PartialOrd for Ipv4FlowSpecNlri<Octs>
1065where Octs: AsRef<[u8]>,
1066{
1067 fn partial_cmp(&self, other: &Ipv4FlowSpecNlri<Octs>) -> Option<cmp::Ordering> {
1068 Some(self.cmp(other))
1069 }
1070}
1071
1072impl<Octs: AsRef<[u8]>> Ord for Ipv4FlowSpecNlri<Octs> {
1073 fn cmp(&self, other: &Self) -> cmp::Ordering {
1074 self.0.cmp(&other.0)
1075 }
1076}
1077
1078#[derive(Copy, Clone, Debug, Hash, PartialEq, Ord, PartialOrd)]
1083#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
1084#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1085pub struct Ipv6UnicastNlri(Prefix);
1086impl AfiSafiNlri for Ipv6UnicastNlri {
1087 type Nlri = Prefix;
1088 fn nlri(&self) -> &Self::Nlri {
1089 &self.0
1090 }
1091}
1092
1093impl FromStr for Ipv6UnicastNlri {
1094 type Err = &'static str;
1095 fn from_str(s: &str) -> Result<Self, Self::Err> {
1096 let p = Prefix::from_str(s).map_err(|_| "could not parse prefix")?;
1097 p.try_into()
1098 }
1099}
1100
1101impl TryFrom<Prefix> for Ipv6UnicastNlri {
1102 type Error = &'static str;
1103 fn try_from(p: Prefix) -> Result<Self, Self::Error> {
1104 if p.is_v6() {
1105 Ok( Self(p) )
1106 } else {
1107 Err("prefix is not IPv6")
1108 }
1109 }
1110}
1111
1112impl TryFrom<(Prefix, PathId)> for Ipv6UnicastAddpathNlri {
1113 type Error = &'static str;
1114
1115 fn try_from((prefix, path_id): (Prefix, PathId)) -> Result<Self, Self::Error> {
1116 Ok(Ipv6UnicastNlri::try_from(prefix)?.into_addpath(path_id))
1117 }
1118}
1119
1120impl<'a, O, P> NlriParse<'a, O, P> for Ipv6UnicastNlri
1121where
1122 O: Octets,
1123 P: 'a + Octets<Range<'a> = O>
1124{
1125 type Output = Self;
1126 fn parse(parser: &mut Parser<'a, P>) -> Result<Self::Output, ParseError> {
1127 Ok(
1128 Self(parse_v6_prefix(parser)?)
1129 )
1130 }
1131}
1132
1133impl NlriCompose for Ipv6UnicastNlri {
1134 fn compose_len(&self) -> usize {
1135 1 + compose_len_prefix(self.prefix())
1137 }
1138
1139 fn compose<Target: OctetsBuilder>(&self, target: &mut Target)
1140 -> Result<(), Target::AppendError>
1141 {
1142 compose_prefix(self.prefix(), target)
1143 }
1144}
1145
1146#[derive(Copy, Clone, Debug, Hash, PartialEq, Ord, PartialOrd)]
1149#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
1150#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1151pub struct Ipv6MulticastNlri(Prefix);
1152
1153impl FromStr for Ipv6MulticastNlri {
1154 type Err = &'static str;
1155 fn from_str(s: &str) -> Result<Self, Self::Err> {
1156 let p = Prefix::from_str(s).map_err(|_| "could not parse prefix")?;
1157 p.try_into()
1158 }
1159}
1160
1161impl TryFrom<Prefix> for Ipv6MulticastNlri {
1162 type Error = &'static str;
1163 fn try_from(p: Prefix) -> Result<Self, Self::Error> {
1164 if p.is_v6() {
1165 Ok( Self(p) )
1166 } else {
1167 Err("prefix is not IPv6")
1168 }
1169 }
1170}
1171
1172impl TryFrom<(Prefix, PathId)> for Ipv6MulticastAddpathNlri {
1173 type Error = &'static str;
1174
1175 fn try_from((prefix, path_id): (Prefix, PathId)) -> Result<Self, Self::Error> {
1176 Ok(Ipv6MulticastNlri::try_from(prefix)?.into_addpath(path_id))
1177 }
1178}
1179
1180impl AfiSafiNlri for Ipv6MulticastNlri {
1181 type Nlri = Prefix;
1182 fn nlri(&self) -> &Self::Nlri {
1183 &self.0
1184 }
1185}
1186
1187impl<'a, O, P> NlriParse<'a, O, P> for Ipv6MulticastNlri
1188where
1189 O: Octets,
1190 P: 'a + Octets<Range<'a> = O>
1191{
1192 type Output = Self;
1193 fn parse(parser: &mut Parser<'a, P>) -> Result<Self::Output, ParseError> {
1194 Ok(
1195 Self(parse_v6_prefix(parser)?)
1196 )
1197 }
1198}
1199
1200impl NlriCompose for Ipv6MulticastNlri {
1201 fn compose_len(&self) -> usize {
1202 1 + compose_len_prefix(self.prefix())
1204 }
1205
1206 fn compose<Target: OctetsBuilder>(&self, target: &mut Target)
1207 -> Result<(), Target::AppendError>
1208 {
1209 compose_prefix(self.prefix(), target)
1210 }
1211}
1212
1213#[derive(Copy, Clone, Debug, Hash)]
1216#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
1217#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1218pub struct Ipv6MplsUnicastNlri<Octs>(MplsNlri<Octs>);
1219
1220impl<Octs> AfiSafiNlri for Ipv6MplsUnicastNlri<Octs> {
1221 type Nlri = MplsNlri<Octs>;
1222 fn nlri(&self) -> &Self::Nlri {
1223 &self.0
1224 }
1225}
1226
1227impl<'a, O, P> NlriParse<'a, O, P> for Ipv6MplsUnicastNlri<O>
1228where
1229 O: Octets,
1230 P: 'a + Octets<Range<'a> = O>
1231{
1232 type Output = Self;
1233
1234 fn parse(parser: &mut Parser<'a, P>)
1235 -> Result<Self::Output, ParseError>
1236 {
1237 Ok(
1238 Self(MplsNlri::parse(parser, Afi::Ipv6)?)
1239 )
1240 }
1241}
1242
1243impl<Octs: AsRef<[u8]>> NlriCompose for Ipv6MplsUnicastNlri<Octs> {
1244 fn compose_len(&self) -> usize {
1245 1 + self.nlri().labels().len() +
1247 prefix_bits_to_bytes(self.nlri().prefix().len())
1248 }
1249
1250 fn compose<Target: OctetsBuilder>(&self, target: &mut Target)
1251 -> Result<(), Target::AppendError> {
1252 self.nlri().compose(target)
1253 }
1254}
1255
1256impl<Octs, Other> PartialEq<Ipv6MplsUnicastNlri<Other>> for Ipv6MplsUnicastNlri<Octs>
1257where Octs: AsRef<[u8]>,
1258 Other: AsRef<[u8]>
1259{
1260 fn eq(&self, other: &Ipv6MplsUnicastNlri<Other>) -> bool {
1261 self.0 == other.0
1262 }
1263}
1264
1265impl<Octs, Other> PartialEq<Ipv6MplsUnicastAddpathNlri<Other>> for Ipv6MplsUnicastAddpathNlri<Octs>
1266where Octs: AsRef<[u8]>,
1267 Other: AsRef<[u8]>
1268{
1269 fn eq(&self, other: &Ipv6MplsUnicastAddpathNlri<Other>) -> bool {
1270 self.0 == other.0
1271 }
1272}
1273
1274impl<Octs> PartialOrd for Ipv6MplsUnicastNlri<Octs>
1275where Octs: AsRef<[u8]>,
1276{
1277 fn partial_cmp(&self, other: &Ipv6MplsUnicastNlri<Octs>) -> Option<cmp::Ordering> {
1278 Some(self.cmp(other))
1279 }
1280}
1281
1282impl<Octs: AsRef<[u8]>> Ord for Ipv6MplsUnicastNlri<Octs> {
1283 fn cmp(&self, other: &Self) -> cmp::Ordering {
1284 self.0.cmp(&other.0)
1285 }
1286}
1287
1288
1289#[derive(Clone, Debug, Hash)]
1292#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
1293#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1294pub struct Ipv6MplsVpnUnicastNlri<Octs>(MplsVpnNlri<Octs>);
1295
1296impl<Octs> AfiSafiNlri for Ipv6MplsVpnUnicastNlri<Octs> {
1297 type Nlri = MplsVpnNlri<Octs>;
1298 fn nlri(&self) -> &Self::Nlri {
1299 &self.0
1300 }
1301}
1302
1303impl<'a, O, P> NlriParse<'a, O, P> for Ipv6MplsVpnUnicastNlri<O>
1304where
1305 O: Octets,
1306 P: 'a + Octets<Range<'a> = O>
1307{
1308 type Output = Self;
1309
1310 fn parse(parser: &mut Parser<'a, P>)
1311 -> Result<Self::Output, ParseError>
1312 {
1313 let (labels, rd, prefix) =
1314 parse_labels_rd_prefix(parser, Afi::Ipv6)?;
1315
1316 Ok(Self(MplsVpnNlri::new(prefix, labels, rd)))
1317 }
1318}
1319
1320impl<Octs: AsRef<[u8]>> NlriCompose for Ipv6MplsVpnUnicastNlri<Octs> {
1321 fn compose_len(&self) -> usize {
1322 1 + self.nlri().compose_len()
1323 }
1324
1325 fn compose<Target: OctetsBuilder>(&self, target: &mut Target)
1326 -> Result<(), Target::AppendError> {
1327 self.nlri().compose(target)
1328 }
1329}
1330
1331
1332impl<Octs, Other> PartialEq<Ipv6MplsVpnUnicastNlri<Other>> for Ipv6MplsVpnUnicastNlri<Octs>
1333where Octs: AsRef<[u8]>,
1334 Other: AsRef<[u8]>
1335{
1336 fn eq(&self, other: &Ipv6MplsVpnUnicastNlri<Other>) -> bool {
1337 self.0 == other.0
1338 }
1339}
1340
1341impl<Octs, Other> PartialEq<Ipv6MplsVpnUnicastAddpathNlri<Other>> for Ipv6MplsVpnUnicastAddpathNlri<Octs>
1342where Octs: AsRef<[u8]>,
1343 Other: AsRef<[u8]>
1344{
1345 fn eq(&self, other: &Ipv6MplsVpnUnicastAddpathNlri<Other>) -> bool {
1346 self.0 == other.0
1347 }
1348}
1349
1350impl<Octs> PartialOrd for Ipv6MplsVpnUnicastNlri<Octs>
1351where Octs: AsRef<[u8]>,
1352{
1353 fn partial_cmp(&self, other: &Ipv6MplsVpnUnicastNlri<Octs>) -> Option<cmp::Ordering> {
1354 Some(self.cmp(other))
1355 }
1356}
1357
1358impl<Octs: AsRef<[u8]>> Ord for Ipv6MplsVpnUnicastNlri<Octs> {
1359 fn cmp(&self, other: &Self) -> cmp::Ordering {
1360 self.0.cmp(&other.0)
1361 }
1362}
1363
1364#[derive(Clone, Debug, Hash)]
1367#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
1368#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1369pub struct Ipv6FlowSpecNlri<Octs>(FlowSpecNlri<Octs>);
1370
1371impl<Octs> AfiSafiNlri for Ipv6FlowSpecNlri<Octs> {
1372 type Nlri = FlowSpecNlri<Octs>;
1373 fn nlri(&self) -> &Self::Nlri {
1374 &self.0
1375 }
1376}
1377
1378impl<'a, O, P> NlriParse<'a, O, P> for Ipv6FlowSpecNlri<O>
1379where
1380 O: Octets,
1381 P: 'a + Octets<Range<'a> = O>
1382{
1383 type Output = Self;
1384
1385 fn parse(parser: &mut Parser<'a, P>)
1386 -> Result<Self::Output, ParseError>
1387 {
1388
1389 Ok(Self(FlowSpecNlri::parse(parser, Afi::Ipv6)?))
1390 }
1391}
1392
1393impl<Octs: AsRef<[u8]>> NlriCompose for Ipv6FlowSpecNlri<Octs> {
1394 fn compose_len(&self) -> usize {
1395 let len = self.nlri().compose_len();
1397 if len >= 240 {
1398 2 + len
1399 } else {
1400 1 + len
1401 }
1402 }
1403
1404 fn compose<Target: OctetsBuilder>(&self, target: &mut Target)
1405 -> Result<(), Target::AppendError> {
1406 self.nlri().compose(target)
1407 }
1408}
1409
1410impl<T> From<Ipv6FlowSpecNlri<T>> for FlowSpecNlri<T> {
1411 fn from(value: Ipv6FlowSpecNlri<T>) -> Self {
1412 value.0
1413 }
1414}
1415
1416impl<Octs, Other> PartialEq<Ipv6FlowSpecNlri<Other>> for Ipv6FlowSpecNlri<Octs>
1417where Octs: AsRef<[u8]>,
1418 Other: AsRef<[u8]>
1419{
1420 fn eq(&self, other: &Ipv6FlowSpecNlri<Other>) -> bool {
1421 self.0 == other.0
1422 }
1423}
1424
1425impl<Octs, Other> PartialEq<Ipv6FlowSpecAddpathNlri<Other>> for Ipv6FlowSpecAddpathNlri<Octs>
1426where Octs: AsRef<[u8]>,
1427 Other: AsRef<[u8]>
1428{
1429 fn eq(&self, other: &Ipv6FlowSpecAddpathNlri<Other>) -> bool {
1430 self.0 == other.0
1431 }
1432}
1433
1434impl<Octs> PartialOrd for Ipv6FlowSpecNlri<Octs>
1435where Octs: AsRef<[u8]>,
1436{
1437 fn partial_cmp(&self, other: &Ipv6FlowSpecNlri<Octs>) -> Option<cmp::Ordering> {
1438 Some(self.cmp(other))
1439 }
1440}
1441
1442impl<Octs: AsRef<[u8]>> Ord for Ipv6FlowSpecNlri<Octs> {
1443 fn cmp(&self, other: &Self) -> cmp::Ordering {
1444 self.0.cmp(&other.0)
1445 }
1446}
1447
1448#[derive(Copy, Clone, Debug, Hash, PartialEq, Ord, PartialOrd)]
1475#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
1476#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1477pub struct L2VpnVplsNlri(VplsNlri);
1478
1479impl AfiSafiNlri for L2VpnVplsNlri {
1480 type Nlri = VplsNlri;
1481 fn nlri(&self) -> &Self::Nlri {
1482 &self.0
1483 }
1484}
1485
1486impl<'a, O, P> NlriParse<'a, O, P> for L2VpnVplsNlri
1487where
1488 O: Octets,
1489 P: 'a + Octets<Range<'a> = O>
1490{
1491 type Output = Self;
1492
1493 fn parse(parser: &mut Parser<'a, P>)
1494 -> Result<Self::Output, ParseError>
1495 {
1496
1497 Ok(Self(VplsNlri::parse(parser)?))
1498 }
1499}
1500
1501impl NlriCompose for L2VpnVplsNlri {
1502 fn compose_len(&self) -> usize {
1503 self.nlri().compose_len()
1504 }
1505
1506 fn compose<Target: OctetsBuilder>(&self, target: &mut Target)
1507 -> Result<(), Target::AppendError> {
1508 self.nlri().compose(target)
1509 }
1510}
1511
1512#[derive(Clone, Debug, Hash)]
1515#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
1516#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1517pub struct L2VpnEvpnNlri<Octs>(EvpnNlri<Octs>);
1518
1519impl<Octs> AfiSafiNlri for L2VpnEvpnNlri<Octs> {
1520 type Nlri = EvpnNlri<Octs>;
1521 fn nlri(&self) -> &Self::Nlri {
1522 &self.0
1523 }
1524}
1525
1526impl<'a, O, P> NlriParse<'a, O, P> for L2VpnEvpnNlri<O>
1527where
1528 O: Octets,
1529 P: 'a + Octets<Range<'a> = O>
1530{
1531 type Output = Self;
1532
1533 fn parse(parser: &mut Parser<'a, P>)
1534 -> Result<Self::Output, ParseError>
1535 {
1536
1537 Ok(Self(EvpnNlri::parse(parser)?))
1538 }
1539}
1540
1541impl<Octs: AsRef<[u8]>> NlriCompose for L2VpnEvpnNlri<Octs> {
1542 fn compose_len(&self) -> usize {
1543 self.nlri().compose_len()
1545 }
1546
1547 fn compose<Target: OctetsBuilder>(&self, target: &mut Target)
1548 -> Result<(), Target::AppendError> {
1549 self.nlri().compose(target)
1550 }
1551}
1552
1553impl<Octs, Other> PartialEq<L2VpnEvpnNlri<Other>> for L2VpnEvpnNlri<Octs>
1554where Octs: AsRef<[u8]>,
1555 Other: AsRef<[u8]>
1556{
1557 fn eq(&self, other: &L2VpnEvpnNlri<Other>) -> bool {
1558 self.0 == other.0
1559 }
1560}
1561
1562impl<Octs, Other> PartialEq<L2VpnEvpnAddpathNlri<Other>> for L2VpnEvpnAddpathNlri<Octs>
1563where Octs: AsRef<[u8]>,
1564 Other: AsRef<[u8]>
1565{
1566 fn eq(&self, other: &L2VpnEvpnAddpathNlri<Other>) -> bool {
1567 self.0 == other.0
1568 }
1569}
1570
1571impl<Octs> PartialOrd for L2VpnEvpnNlri<Octs>
1572where Octs: AsRef<[u8]>,
1573{
1574 fn partial_cmp(&self, other: &L2VpnEvpnNlri<Octs>) -> Option<cmp::Ordering> {
1575 Some(self.cmp(other))
1576 }
1577}
1578
1579impl<Octs: AsRef<[u8]>> Ord for L2VpnEvpnNlri<Octs> {
1580 fn cmp(&self, other: &Self) -> cmp::Ordering {
1581 self.0.cmp(&other.0)
1582 }
1583}
1584
1585pub struct NlriIter<'a, O, P, ASP> {
1609 parser: Parser<'a, P>,
1610 asp: std::marker::PhantomData<ASP>,
1611 output: std::marker::PhantomData<O>,
1612}
1613
1614impl<'a, O, P, ASP> NlriIter<'a, O, P, ASP>
1615where
1616 O: Octets,
1617 P: Octets<Range<'a> = O>,
1618 ASP: NlriParse<'a, O, P>
1619{
1620 pub const fn new(parser: Parser<'a, P>) -> Self {
1621 NlriIter {
1622 parser,
1623 asp: std::marker::PhantomData,
1624 output: std::marker::PhantomData
1625 }
1626 }
1627
1628 pub fn afi_safi(&self) -> AfiSafiType {
1629 ASP::Output::afi_safi()
1630 }
1631
1632 pub fn nlri_type(&self) -> NlriType {
1633 ASP::nlri_type()
1634 }
1635
1636 pub fn validate(&self) -> Result<(), ParseError> {
1640 let mut parser = self.parser;
1641 while parser.remaining() > 0 {
1642 ASP::parse(&mut parser)?;
1644 }
1645 Ok(())
1646 }
1647}
1648
1649
1650impl<'a, O, P, ASP: NlriParse<'a, O, P>> Iterator for NlriIter<'a, O, P, ASP>
1651where
1652 P: Octets<Range<'a> = O>
1653{
1654 type Item = Result<ASP::Output, ParseError>;
1655
1656 fn next(&mut self) -> Option<Self::Item> {
1657 if self.parser.remaining() == 0 {
1658 return None;
1659 }
1660 Some(ASP::parse(&mut self.parser))
1661 }
1662}
1663
1664pub struct NlriEnumIter<'a, P> {
1667 parser: Parser<'a, P>,
1668 ty: NlriType,
1669}
1670
1671impl<'a, P> NlriEnumIter<'a, P> {
1672 pub const fn new(parser: Parser<'a, P>, ty: NlriType) -> Self {
1673 Self { parser, ty }
1674 }
1675
1676 pub const fn nlri_type(&self) -> NlriType {
1677 self.ty
1678 }
1679
1680 pub const fn afi_safi(&self) -> AfiSafiType {
1681 self.ty.afi_safi()
1682 }
1683}
1684
1685impl<'a, O, P> Iterator for NlriEnumIter<'a, P>
1686where
1687 O: Octets,
1688 P: Octets<Range<'a> = O>,
1689{
1690 type Item = Result<Nlri<O>, ParseError>;
1691
1692 fn next(&mut self) -> Option<Self::Item> {
1693 if self.parser.remaining() == 0 {
1694 return None
1695 }
1696
1697 let res = match self.ty {
1698 NlriType::Ipv4Unicast => Ipv4UnicastNlri::parse(&mut self.parser).map(Nlri::Ipv4Unicast),
1699 NlriType::Ipv4UnicastAddpath => Ipv4UnicastAddpathNlri::parse(&mut self.parser).map(Nlri::Ipv4UnicastAddpath),
1700 NlriType::Ipv4Multicast => Ipv4MulticastNlri::parse(&mut self.parser).map(Nlri::Ipv4Multicast),
1701 NlriType::Ipv4MulticastAddpath => Ipv4MulticastAddpathNlri::parse(&mut self.parser).map(Nlri::Ipv4MulticastAddpath),
1702 NlriType::Ipv4MplsUnicast => Ipv4MplsUnicastNlri::parse(&mut self.parser).map(Nlri::Ipv4MplsUnicast),
1703 NlriType::Ipv4MplsUnicastAddpath => Ipv4MplsUnicastAddpathNlri::parse(&mut self.parser).map(Nlri::Ipv4MplsUnicastAddpath),
1704 NlriType::Ipv4MplsVpnUnicast => Ipv4MplsVpnUnicastNlri::parse(&mut self.parser).map(Nlri::Ipv4MplsVpnUnicast),
1705 NlriType::Ipv4MplsVpnUnicastAddpath => Ipv4MplsVpnUnicastAddpathNlri::parse(&mut self.parser).map(Nlri::Ipv4MplsVpnUnicastAddpath),
1706 NlriType::Ipv4RouteTarget => Ipv4RouteTargetNlri::parse(&mut self.parser).map(Nlri::Ipv4RouteTarget),
1707 NlriType::Ipv4RouteTargetAddpath => Ipv4RouteTargetAddpathNlri::parse(&mut self.parser).map(Nlri::Ipv4RouteTargetAddpath),
1708 NlriType::Ipv4FlowSpec => Ipv4FlowSpecNlri::parse(&mut self.parser).map(Nlri::Ipv4FlowSpec),
1709 NlriType::Ipv4FlowSpecAddpath => Ipv4FlowSpecAddpathNlri::parse(&mut self.parser).map(Nlri::Ipv4FlowSpecAddpath),
1710 NlriType::Ipv6Unicast => Ipv6UnicastNlri::parse(&mut self.parser).map(Nlri::Ipv6Unicast),
1711 NlriType::Ipv6UnicastAddpath => Ipv6UnicastAddpathNlri::parse(&mut self.parser).map(Nlri::Ipv6UnicastAddpath),
1712 NlriType::Ipv6Multicast => Ipv6MulticastNlri::parse(&mut self.parser).map(Nlri::Ipv6Multicast),
1713 NlriType::Ipv6MulticastAddpath => Ipv6MulticastAddpathNlri::parse(&mut self.parser).map(Nlri::Ipv6MulticastAddpath),
1714 NlriType::Ipv6MplsUnicast => Ipv6MplsUnicastNlri::parse(&mut self.parser).map(Nlri::Ipv6MplsUnicast),
1715 NlriType::Ipv6MplsUnicastAddpath => Ipv6MplsUnicastAddpathNlri::parse(&mut self.parser).map(Nlri::Ipv6MplsUnicastAddpath),
1716 NlriType::Ipv6MplsVpnUnicast => Ipv6MplsVpnUnicastNlri::parse(&mut self.parser).map(Nlri::Ipv6MplsVpnUnicast),
1717 NlriType::Ipv6MplsVpnUnicastAddpath => Ipv6MplsVpnUnicastAddpathNlri::parse(&mut self.parser).map(Nlri::Ipv6MplsVpnUnicastAddpath),
1718 NlriType::Ipv6FlowSpec => Ipv6FlowSpecNlri::parse(&mut self.parser).map(Nlri::Ipv6FlowSpec),
1719 NlriType::Ipv6FlowSpecAddpath => Ipv6FlowSpecAddpathNlri::parse(&mut self.parser).map(Nlri::Ipv6FlowSpecAddpath),
1720 NlriType::L2VpnVpls => L2VpnVplsNlri::parse(&mut self.parser).map(Nlri::L2VpnVpls),
1721 NlriType::L2VpnVplsAddpath => L2VpnVplsAddpathNlri::parse(&mut self.parser).map(Nlri::L2VpnVplsAddpath),
1722 NlriType::L2VpnEvpn => L2VpnEvpnNlri::parse(&mut self.parser).map(Nlri::L2VpnEvpn),
1723 NlriType::L2VpnEvpnAddpath => L2VpnEvpnAddpathNlri::parse(&mut self.parser).map(Nlri::L2VpnEvpnAddpath),
1724 NlriType::Unsupported(..) => { return None; }
1725 };
1726
1727 Some(res)
1728 }
1729}
1730
1731impl<'a, O, P, ASP> From<NlriIter<'a, O, P, ASP>> for NlriEnumIter<'a, P>
1732where
1733 O: Octets,
1734 ASP: NlriParse<'a, O, P>,
1735 P: Octets<Range<'a> = O>,
1736{
1737 fn from(iter: NlriIter<'a, O, P, ASP>) -> Self {
1738 Self {
1739 parser: iter.parser,
1740 ty: ASP::nlri_type()
1741 }
1742 }
1743}
1744
1745impl<'a, O, P, ASP: NlriParse<'a, O, P>> NlriIter<'a, O, P, ASP>
1746where
1747 O: Octets,
1748 P: Octets<Range<'a> = O>
1749{
1750 pub fn next_with<T, F: FnOnce(<Self as Iterator>::Item) -> T>(&mut self, fmap: F) -> Option<T> {
1751 self.next().map(fmap)
1752 }
1753}
1754
1755impl<'a, O, P> NlriEnumIter<'a, P>
1756where
1757 O: Octets,
1758 P: Octets<Range<'a> = O>,
1759{
1760 pub fn next_with<T, F: FnOnce(<Self as Iterator>::Item) -> T>(&mut self, fmap: F) -> Option<T> {
1761 self.next().map(fmap)
1762 }
1763}
1764
1765#[cfg(test)]
1766mod tests {
1767
1768 use super::*;
1769 use inetnum::addr::Prefix;
1770 use std::str::FromStr;
1771
1772 #[test]
1773 fn parse_ipv4unicast() {
1774 let raw = vec![24,1,2,3];
1775 let mut parser = Parser::from_ref(&raw);
1776 let n = Ipv4UnicastNlri::parse(&mut parser).unwrap();
1777
1778 assert_eq!(n.prefix(), Prefix::from_str("1.2.3.0/24").unwrap());
1779 }
1780
1781 #[test]
1782 fn parse_ipv4mplsunicast() {
1783 let raw = vec![0x38, 0x01, 0xf4, 0x01, 0x0a, 0x00, 0x00, 0x09];
1785 let mut parser = Parser::from_ref(&raw);
1786 let n = Ipv4MplsUnicastNlri::parse(&mut parser).unwrap();
1787 eprintln!("{}", &n);
1788
1789 let raw = bytes::Bytes::from_static(&[0x38, 0x01, 0xf4, 0x01, 0x0a, 0x00, 0x00, 0x09]);
1790 let mut parser = Parser::from_ref(&raw);
1791 let n2 = Ipv4MplsUnicastNlri::parse(&mut parser).unwrap();
1792 eprintln!("{}", &n2);
1793
1794 assert_eq!(n, n2);
1795
1796 let _n: Nlri<_> = n.into();
1797 let _n2: Nlri<_> = n2.into();
1798 }
1799
1800 #[test]
1801 fn display() {
1802 let p = Prefix::from_str("1.2.3.0/24").unwrap();
1803 let n: Nlri<()> = Ipv4UnicastNlri(p).into();
1804 assert_eq!(n.to_string(), p.to_string());
1805 }
1806
1807 #[test]
1808 fn iter() {
1809 let raw = vec![
1810 0x38, 0x01, 0xf4, 0x01, 0x0a, 0x00, 0x00, 0x09,
1811 0x38, 0x01, 0xf4, 0x01, 0x0a, 0x00, 0x00, 0x0a,
1812 ];
1813 let parser = Parser::from_ref(&raw);
1814 let iter = NlriIter::ipv4_mplsunicast(parser);
1815 assert_eq!(iter.count(), 2);
1816 }
1817
1818 #[test]
1819 fn iter_generic() {
1820 let mpls_raw = vec![
1821 0x38, 0x01, 0xf4, 0x01, 0x0a, 0x00, 0x00, 0x09,
1822 0x38, 0x01, 0xf4, 0x01, 0x0a, 0x00, 0x00, 0x0a,
1823 ];
1824 let parser = Parser::from_ref(&mpls_raw);
1825 let mpls_iter = NlriIter::ipv4_mplsunicast(parser);
1826
1827 let v4_raw = vec![24, 1, 2, 3];
1828 let parser = Parser::from_ref(&v4_raw);
1829 let v4_iter = NlriIter::ipv4_unicast(parser);
1830
1831
1832 for n in NlriEnumIter::from(v4_iter)
1833 .chain(NlriEnumIter::from(mpls_iter))
1834 {
1835 dbg!(&n);
1836 }
1837 }
1838
1839 #[test]
1840 fn iter_addpath() {
1841 let raw = vec![
1842 0, 0, 0, 1, 24, 1, 2, 1,
1843 0, 0, 0, 2, 24, 1, 2, 2,
1844 0, 0, 0, 3, 24, 1, 2, 3,
1845 0, 0, 0, 4, 24, 1, 2, 4,
1846 ];
1847
1848 let parser = Parser::from_ref(&raw);
1849 let iter = NlriIter::ipv4_unicast_addpath(parser);
1850 assert_eq!(iter.count(), 4);
1851
1852 let iter = NlriIter::ipv4_unicast_addpath(parser);
1853 for n in iter.map(|e| e.unwrap().prefix()) {
1854 dbg!(&n);
1855 }
1856 }
1857
1858 #[test]
1859 fn iter_addpath_alternative() {
1860 let raw = vec![
1861 0, 0, 0, 1, 24, 1, 2, 1,
1862 0, 0, 0, 2, 24, 1, 2, 2,
1863 0, 0, 0, 3, 24, 1, 2, 3,
1864 0, 0, 0, 4, 24, 1, 2, 4,
1865 ];
1866
1867 let parser = Parser::from_ref(&raw);
1868 let iter = NlriIter::ipv6_unicast_addpath(parser);
1869 for n in iter {
1871 eprintln!("{}", n.unwrap());
1872 }
1873 }
1874
1875 #[test]
1876 fn iter_with() {
1877 let raw = vec![
1878 0, 0, 0, 1, 24, 1, 2, 1,
1879 0, 0, 0, 2, 24, 1, 2, 2,
1880 0, 0, 0, 3, 24, 1, 2, 3,
1881 0, 0, 0, 4, 24, 1, 2, 4,
1882 ];
1883
1884 let parser = Parser::from_ref(&raw);
1885 let iter = NlriIter::ipv6_unicast_addpath(parser);
1886 for x in iter.map(|e| format!("IPv6!!!: {:?}", e).to_string()) {
1891 dbg!(x);
1892 }
1893
1894 }
1895
1896 #[test]
1897 fn roundtrip_into_from_addpath() {
1898 let raw = vec![
1899 24, 1, 2, 1,
1900 24, 1, 2, 2,
1901 24, 1, 2, 3,
1902 24, 1, 2, 4,
1903 ];
1904
1905 let parser = Parser::from_ref(&raw);
1906 let iter = NlriIter::ipv6_unicast(parser);
1907 for (idx, n) in iter.enumerate() {
1908 dbg!(
1909 Ipv6UnicastNlri::from(
1910 dbg!(n.unwrap().into_addpath(PathId(idx.try_into().unwrap())))
1911 )
1912 );
1913 }
1914 }
1915
1916}