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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
use byteorder::{ByteOrder, NativeEndian};
use std::mem::size_of;

use constants::*;
use utils::parse_u32;
use {DefaultNla, Nla, NlaBuffer, Parseable, Result};

#[derive(Debug, PartialEq, Eq, Clone)]
pub enum RouteMetricsNla {
    Unspec(Vec<u8>),
    Lock(u32),
    Mtu(u32),
    Window(u32),
    Rtt(u32),
    RttVar(u32),
    SsThresh(u32),
    Cwnd(u32),
    Advmss(u32),
    Reordering(u32),
    Hoplimit(u32),
    InitCwnd(u32),
    Features(u32),
    RtoMin(u32),
    InitRwnd(u32),
    QuickAck(u32),
    CcAlgo(u32),
    FastopenNoCookie(u32),
    Other(DefaultNla),
}

impl Nla for RouteMetricsNla {
    #[cfg_attr(nightly, rustfmt::skip)]
    fn value_len(&self) -> usize {
        use self::RouteMetricsNla::*;
        match *self {
            Unspec(ref bytes) => bytes.len(),
            Lock(_)
                | Mtu(_)
                | Window(_)
                | Rtt(_)
                | RttVar(_)
                | SsThresh(_)
                | Cwnd(_)
                | Advmss(_)
                | Reordering(_)
                | Hoplimit(_)
                | InitCwnd(_)
                | Features(_)
                | RtoMin(_)
                | InitRwnd(_)
                | QuickAck(_)
                | CcAlgo(_)
                | FastopenNoCookie(_)
                => size_of::<u32>(),
            Other(ref attr) => attr.value_len(),
        }
    }

    #[cfg_attr(nightly, rustfmt::skip)]
    fn emit_value(&self, buffer: &mut [u8]) {
        use self::RouteMetricsNla::*;
        match *self {
            Unspec(ref bytes) => buffer.copy_from_slice(bytes.as_slice()),

            Lock(value)
                | Mtu(value)
                | Window(value)
                | Rtt(value)
                | RttVar(value)
                | SsThresh(value)
                | Cwnd(value)
                | Advmss(value)
                | Reordering(value)
                | Hoplimit(value)
                | InitCwnd(value)
                | Features(value)
                | RtoMin(value)
                | InitRwnd(value)
                | QuickAck(value)
                | CcAlgo(value)
                | FastopenNoCookie(value)
                => NativeEndian::write_u32(buffer, value),

            Other(ref attr) => attr.emit_value(buffer),
        }
    }

    fn kind(&self) -> u16 {
        use self::RouteMetricsNla::*;
        match *self {
            Unspec(_) => RTAX_UNSPEC,
            Lock(_) => RTAX_LOCK,
            Mtu(_) => RTAX_MTU,
            Window(_) => RTAX_WINDOW,
            Rtt(_) => RTAX_RTT,
            RttVar(_) => RTAX_RTTVAR,
            SsThresh(_) => RTAX_SSTHRESH,
            Cwnd(_) => RTAX_CWND,
            Advmss(_) => RTAX_ADVMSS,
            Reordering(_) => RTAX_REORDERING,
            Hoplimit(_) => RTAX_HOPLIMIT,
            InitCwnd(_) => RTAX_INITCWND,
            Features(_) => RTAX_FEATURES,
            RtoMin(_) => RTAX_RTO_MIN,
            InitRwnd(_) => RTAX_INITRWND,
            QuickAck(_) => RTAX_QUICKACK,
            CcAlgo(_) => RTAX_CC_ALGO,
            FastopenNoCookie(_) => RTAX_FASTOPEN_NO_COOKIE,
            Other(ref attr) => attr.kind(),
        }
    }
}

impl<'buffer, T: AsRef<[u8]> + ?Sized> Parseable<RouteMetricsNla> for NlaBuffer<&'buffer T> {
    fn parse(&self) -> Result<RouteMetricsNla> {
        use self::RouteMetricsNla::*;
        let payload = self.value();
        Ok(match self.kind() {
            RTAX_UNSPEC => Unspec(payload.to_vec()),
            RTAX_LOCK => Lock(parse_u32(payload)?),
            RTAX_MTU => Mtu(parse_u32(payload)?),
            RTAX_WINDOW => Window(parse_u32(payload)?),
            RTAX_RTT => Rtt(parse_u32(payload)?),
            RTAX_RTTVAR => RttVar(parse_u32(payload)?),
            RTAX_SSTHRESH => SsThresh(parse_u32(payload)?),
            RTAX_CWND => Cwnd(parse_u32(payload)?),
            RTAX_ADVMSS => Advmss(parse_u32(payload)?),
            RTAX_REORDERING => Reordering(parse_u32(payload)?),
            RTAX_HOPLIMIT => Hoplimit(parse_u32(payload)?),
            RTAX_INITCWND => InitCwnd(parse_u32(payload)?),
            RTAX_FEATURES => Features(parse_u32(payload)?),
            RTAX_RTO_MIN => RtoMin(parse_u32(payload)?),
            RTAX_INITRWND => InitRwnd(parse_u32(payload)?),
            RTAX_QUICKACK => QuickAck(parse_u32(payload)?),
            RTAX_CC_ALGO => CcAlgo(parse_u32(payload)?),
            RTAX_FASTOPEN_NO_COOKIE => FastopenNoCookie(parse_u32(payload)?),
            _ => Other(<Self as Parseable<DefaultNla>>::parse(self)?),
        })
    }
}