summaryrefslogtreecommitdiff
path: root/src/protocol/mpls.rs
blob: 2f441f96cb3a865ee70431da430c9d1491bbfdc3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
use crate::protocol::codec::Decode;
use nom::bits;
use nom::error::Error;
use nom::number;
use nom::sequence;
use nom::IResult;

/******************************************************************************
 * Struct
 ******************************************************************************/

#[derive(Debug, PartialEq)]
pub struct MPLSHeader {
    pub label: u32,
    pub experimental: u8,
    pub bottom_of_stack: bool,
    pub ttl: u8,
}

// Ethernet pseudowire (PW) https://tools.ietf.org/html/rfc4448#section-3.1
#[derive(Debug, PartialEq)]
pub struct PWEthHeader {
    pub control_word: u32,
}

/******************************************************************************
 * API
 ******************************************************************************/

fn bit_decode(input: &[u8]) -> IResult<&[u8], (u32, u8, u8, u8)> {
    bits::bits::<_, _, Error<_>, _, _>(sequence::tuple((
        bits::streaming::take(20u8),
        bits::streaming::take(3u8),
        bits::streaming::take(1u8),
        bits::streaming::take(8u8),
    )))(input)
}

impl Decode for MPLSHeader {
    type Iterm = MPLSHeader;
    fn decode(input: &[u8]) -> IResult<&[u8], MPLSHeader> {
        let (input, (label, experimental, bottom_of_stack, ttl)) = bit_decode(input)?;

        Ok((
            input,
            MPLSHeader {
                label,
                experimental,
                bottom_of_stack: bottom_of_stack == 1,
                ttl,
            },
        ))
    }
}

impl Decode for PWEthHeader {
    type Iterm = PWEthHeader;
    fn decode(input: &[u8]) -> IResult<&[u8], PWEthHeader> {
        let (input, control_word) = number::streaming::be_u32(input)?;

        Ok((input, PWEthHeader { control_word }))
    }
}

/******************************************************************************
 * TEST
 ******************************************************************************/

#[cfg(test)]
mod tests {
    use super::MPLSHeader;
    use crate::protocol::codec::Decode;
    const LAST_SLICE: &'static [u8] = &[0xff];

    #[test]
    fn mpls_header_decode() {
        /*
         * MultiProtocol Label Switching Header, Label: 18, Exp: 5, S: 0, TTL: 255
         *     0000 0000 0000 0001 0010 .... .... .... = MPLS Label: 18 (0x00012)
         *     .... .... .... .... .... 101. .... .... = MPLS Experimental Bits: 5
         *     .... .... .... .... .... ...0 .... .... = MPLS Bottom Of Label Stack: 0
         *     .... .... .... .... .... .... 1111 1111 = MPLS TTL: 255
         * MultiProtocol Label Switching Header, Label: 16, Exp: 5, S: 1, TTL: 255
         *     0000 0000 0000 0001 0000 .... .... .... = MPLS Label: 16 (0x00010)
         *     .... .... .... .... .... 101. .... .... = MPLS Experimental Bits: 5
         *     .... .... .... .... .... ...1 .... .... = MPLS Bottom Of Label Stack: 1
         *     .... .... .... .... .... .... 1111 1111 = MPLS TTL: 255
         */

        let bytes = [0x00, 0x01, 0x2a, 0xff, 0x00, 0x01, 0x0b, 0xff, 0xff];

        let expectation1 = MPLSHeader {
            label: 18,
            experimental: 5,
            bottom_of_stack: false,
            ttl: 255,
        };
        let expectation2 = MPLSHeader {
            label: 16,
            experimental: 5,
            bottom_of_stack: true,
            ttl: 255,
        };

        assert_eq!(MPLSHeader::decode(&bytes), Ok((&bytes[4..], expectation1)));
        assert_eq!(
            MPLSHeader::decode(&bytes[4..]),
            Ok((LAST_SLICE, expectation2))
        );

        // example
        let mut payload = &bytes[..];
        while let Ok((remain, header)) = MPLSHeader::decode(payload) {
            println!("return: {:?}, payload: {}", header, remain.len());
            payload = remain;
            if header.bottom_of_stack {
                break;
            }
        }

        // assert_eq!(1, 0);
    }
}