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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
|
<table class="head">
<tr>
<td class="head-ltitle">NG_PIPE(4)</td>
<td class="head-vol">Device Drivers Manual</td>
<td class="head-rtitle">NG_PIPE(4)</td>
</tr>
</table>
<div class="manual-text">
<section class="Sh">
<h1 class="Sh" id="NAME"><a class="permalink" href="#NAME">NAME</a></h1>
<p class="Pp"><code class="Nm">ng_pipe</code> — <span class="Nd">Traffic
manipulating netgraph node type</span></p>
</section>
<section class="Sh">
<h1 class="Sh" id="SYNOPSIS"><a class="permalink" href="#SYNOPSIS">SYNOPSIS</a></h1>
<p class="Pp"><code class="In">#include
<<a class="In">netgraph/ng_pipe.h</a>></code></p>
</section>
<section class="Sh">
<h1 class="Sh" id="DESCRIPTION"><a class="permalink" href="#DESCRIPTION">DESCRIPTION</a></h1>
<p class="Pp">The <code class="Nm">pipe</code> node type manipulates traffic by
emulating bandwidth and delay, as well as random packet losses.</p>
</section>
<section class="Sh">
<h1 class="Sh" id="HOOKS"><a class="permalink" href="#HOOKS">HOOKS</a></h1>
<p class="Pp">This node type supports the following hooks:</p>
<dl class="Bl-tag">
<dt id="upper"><var class="Va">upper</var></dt>
<dd>Hook leading to upper layer protocols.</dd>
<dt id="lower"><var class="Va">lower</var></dt>
<dd>Hook leading to lower layer protocols.</dd>
</dl>
<p class="Pp" id="downstream">Traffic flowing from <var class="Va">upper</var>
to <var class="Va">lower</var> is considered
<a class="permalink" href="#downstream"><b class="Sy">downstream</b></a>
traffic. Traffic flowing from <var class="Va">lower</var> to
<var class="Va">upper</var> is considered
<a class="permalink" href="#upstream"><b class="Sy" id="upstream">upstream</b></a>
traffic.</p>
</section>
<section class="Sh">
<h1 class="Sh" id="MODE_OF_OPERATION"><a class="permalink" href="#MODE_OF_OPERATION">MODE
OF OPERATION</a></h1>
<p class="Pp">Data received on a hook - both in upstream and downstream
direction - is put into an inbound queue. If inbound queue is full, discard
one frame depending on dropping policy (from the head or from the tail of
the queue).</p>
<p class="Pp">There are three mutually exclusive modes for the input queue:</p>
<dl class="Bl-tag">
<dt id="First"><a class="permalink" href="#First"><code class="Dv">First In
First Out (FIFO)</code></a></dt>
<dd>A single queue holds packets in chronological order.</dd>
<dt id="Weighted"><a class="permalink" href="#Weighted"><code class="Dv">Weighted
fair queuing (WFQ)</code></a></dt>
<dd>There are multiple queues for different traffic flows (based on IPv4 IPs).
The longest queue is truncated if necessary. This approach assumes that
the stalling flow is the flow with the most packets currently on
hold.</dd>
<dt id="Deficit"><a class="permalink" href="#Deficit"><code class="Dv">Deficit
Round Robin (DRR)</code></a></dt>
<dd>This mode is similar to WFQ, but packets are not taken out in strict
chronological order. In principle oldest packets come first, but not too
many packets from the same flow.</dd>
</dl>
<p class="Pp">It is possible to configure a duplication probability. As the dice
decides, the currently active packet stays in the queue while a copy of the
packet is sent out. Nothing prevents a packet from being duplicated multiple
times.</p>
<p class="Pp">Packets are dropped with an increasing probability depending on
the size of the packet, if a <var class="Va">ber</var> (bit error rate) is
configured.</p>
<p class="Pp">Surviving packets are delayed by the time the packet would need to
travel through a link of the configured bandwidth. If this outbound queue is
full, the packet is dropped.</p>
</section>
<section class="Sh">
<h1 class="Sh" id="CONTROL_MESSAGES"><a class="permalink" href="#CONTROL_MESSAGES">CONTROL
MESSAGES</a></h1>
<p class="Pp">This node type supports the generic control messages and the
following specific messages.</p>
<dl class="Bl-tag">
<dt id="NGM_PIPE_SET_CFG"><a class="permalink" href="#NGM_PIPE_SET_CFG"><code class="Dv">NGM_PIPE_SET_CFG</code></a>
(<code class="Ic">setcfg</code>)</dt>
<dd>Set node configuration to the one specified in <var class="Vt">struct
ng_pipe_cfg</var>
<p class="Pp">Note: To set a value to zero, specify -1 instead. This allows
omitting configuration values, which should not be modified.</p>
</dd>
<dt id="NGM_PIPE_GET_CFG"><a class="permalink" href="#NGM_PIPE_GET_CFG"><code class="Dv">NGM_PIPE_GET_CFG</code></a>
(<code class="Ic">getcfg</code>)</dt>
<dd>Return current node configuration as <var class="Vt">struct
ng_pipe_cfg</var>
<div class="Bd Pp Li">
<pre>struct ng_pipe_cfg {
u_int64_t bandwidth; /* bits per second */
u_int64_t delay; /* additional delay, usec */
u_int32_t header_offset; /* offset of IP header in bytes */
u_int32_t overhead; /* assumed L2 overhead in bytes */
struct ng_pipe_hookcfg downstream;
struct ng_pipe_hookcfg upstream;
};
/* Config structure for one hook */
struct ng_pipe_hookcfg {
u_int64_t bandwidth; /* bits per second */
u_int64_t ber; /* avg. interval between bit errors (1 / BER) */
u_int32_t qin_size_limit; /* number of queue items */
u_int32_t qout_size_limit; /* number of queue items */
u_int32_t duplicate; /* probability in % */
u_int32_t fifo; /* 0 = off, 1 = on */
u_int32_t drr; /* 0 = off, 1 = 2048 bytes, or x bytes */
u_int32_t wfq; /* 0 = off, 1 = on */
u_int32_t droptail; /* 0 = off, 1 = on */
u_int32_t drophead; /* 0 = off, 1 = on */
};</pre>
</div>
</dd>
<dt id="NGM_PIPE_GET_STATS"><a class="permalink" href="#NGM_PIPE_GET_STATS"><code class="Dv">NGM_PIPE_GET_STATS</code></a>
(<code class="Ic">getstats</code>)</dt>
<dd>Return node statistics as <var class="Vt">struct ng_pipe_stats</var>
<div class="Bd Pp Li">
<pre>/* Statistics structure for one hook */
struct ng_pipe_hookstat {
u_int64_t fwd_octets;
u_int64_t fwd_frames;
u_int64_t in_disc_octets;
u_int64_t in_disc_frames;
u_int64_t out_disc_octets;
u_int64_t out_disc_frames;
};
/* Statistics structure returned by NGM_PIPE_GET_STATS */
struct ng_pipe_stats {
struct ng_pipe_hookstat downstream;
struct ng_pipe_hookstat upstream;
};</pre>
</div>
</dd>
<dt id="NGM_PIPE_CLR_STATS"><a class="permalink" href="#NGM_PIPE_CLR_STATS"><code class="Dv">NGM_PIPE_CLR_STATS</code></a>
(<code class="Ic">clrstats</code>)</dt>
<dd>Clear node statistics.</dd>
<dt id="NGM_PIPE_GETCLR_STATS"><a class="permalink" href="#NGM_PIPE_GETCLR_STATS"><code class="Dv">NGM_PIPE_GETCLR_STATS</code></a>
(<code class="Ic">getclrstats</code>)</dt>
<dd>Atomically return and clear node statistics.</dd>
<dt id="NGM_PIPE_GET_RUN"><a class="permalink" href="#NGM_PIPE_GET_RUN"><code class="Dv">NGM_PIPE_GET_RUN</code></a>
(<code class="Ic">getrun</code>)</dt>
<dd>Return node statistics as <var class="Vt">struct ng_pipe_run</var>
<div class="Bd Pp Li">
<pre>/* Runtime structure for one hook */
struct ng_pipe_hookrun {
u_int32_t fifo_queues;
u_int32_t qin_octets;
u_int32_t qin_frames;
u_int32_t qout_octets;
u_int32_t qout_frames;
};
/* Runtime structure returned by NGM_PIPE_GET_RUN */
struct ng_pipe_run {
struct ng_pipe_hookrun downstream;
struct ng_pipe_hookrun upstream;
};</pre>
</div>
</dd>
</dl>
</section>
<section class="Sh">
<h1 class="Sh" id="SHUTDOWN"><a class="permalink" href="#SHUTDOWN">SHUTDOWN</a></h1>
<p class="Pp">This node shuts down upon receipt of a
<code class="Dv">NGM_SHUTDOWN</code> control message, or when all hooks have
been disconnected.</p>
</section>
<section class="Sh">
<h1 class="Sh" id="EXAMPLES"><a class="permalink" href="#EXAMPLES">EXAMPLES</a></h1>
<p class="Pp">Limit outgoing data rate over fxp0 Ethernet interface to 20Mbps in
fifo mode and incoming to 50kbps in drr mode and 2% duplicate
probability.</p>
<div class="Bd Pp Bd-indent Li">
<pre>/usr/sbin/ngctl -f- <<-SEQ
mkpeer fxp0: pipe lower lower
name fxp0:lower fxp0_pipe
connect fxp0: fxp0_pipe: upper upper
msg fxp0_pipe: setcfg { downstream={ bandwidth=20000000 fifo=1 } }
msg fxp0_pipe: setcfg { upstream={ bandwidth=500000 drr=1 duplicate=2 } }
SEQ</pre>
</div>
</section>
<section class="Sh">
<h1 class="Sh" id="SEE_ALSO"><a class="permalink" href="#SEE_ALSO">SEE
ALSO</a></h1>
<p class="Pp"><a class="Xr">netgraph(4)</a>, <a class="Xr">ngctl(8)</a></p>
</section>
<section class="Sh">
<h1 class="Sh" id="AUTHORS"><a class="permalink" href="#AUTHORS">AUTHORS</a></h1>
<p class="Pp"><span class="An">Lutz Donnerhacke</span>
<<a class="Mt" href="mailto:lutz@donnerhacke.de">lutz@donnerhacke.de</a>>
(man page)</p>
</section>
<section class="Sh">
<h1 class="Sh" id="BUGS"><a class="permalink" href="#BUGS">BUGS</a></h1>
<p class="Pp">Error handling for memory issues is missing. If kernel memory
cannot be allocated immediately, a kernel panic will be triggered. Same
happens if an mbuf is fragmented within the transport headers.</p>
</section>
</div>
<table class="foot">
<tr>
<td class="foot-date">October 17, 2019</td>
<td class="foot-os">FreeBSD 15.0</td>
</tr>
</table>
|