1 package netlink
2
3 import (
4 "bytes"
5 "encoding/binary"
6 "encoding/hex"
7 "errors"
8 "fmt"
9 "net"
10 "syscall"
11
12 "github.com/vishvananda/netlink/nl"
13 "golang.org/x/sys/unix"
14 )
15
16
17 const (
18 TC_U32_TERMINAL = nl.TC_U32_TERMINAL
19 TC_U32_OFFSET = nl.TC_U32_OFFSET
20 TC_U32_VAROFFSET = nl.TC_U32_VAROFFSET
21 TC_U32_EAT = nl.TC_U32_EAT
22 )
23
24
25
26
27 type TcU32Sel = nl.TcU32Sel
28
29
30
31
32 type TcU32Key = nl.TcU32Key
33
34
35 type U32 struct {
36 FilterAttrs
37 ClassId uint32
38 Divisor uint32
39 Hash uint32
40 Link uint32
41 RedirIndex int
42 Sel *TcU32Sel
43 Actions []Action
44 Police *PoliceAction
45 }
46
47 func (filter *U32) Attrs() *FilterAttrs {
48 return &filter.FilterAttrs
49 }
50
51 func (filter *U32) Type() string {
52 return "u32"
53 }
54
55 type Flower struct {
56 FilterAttrs
57 DestIP net.IP
58 DestIPMask net.IPMask
59 SrcIP net.IP
60 SrcIPMask net.IPMask
61 EthType uint16
62 EncDestIP net.IP
63 EncDestIPMask net.IPMask
64 EncSrcIP net.IP
65 EncSrcIPMask net.IPMask
66 EncDestPort uint16
67 EncKeyId uint32
68 SkipHw bool
69 SkipSw bool
70 IPProto *nl.IPProto
71 DestPort uint16
72 SrcPort uint16
73
74 Actions []Action
75 }
76
77 func (filter *Flower) Attrs() *FilterAttrs {
78 return &filter.FilterAttrs
79 }
80
81 func (filter *Flower) Type() string {
82 return "flower"
83 }
84
85 func (filter *Flower) encodeIP(parent *nl.RtAttr, ip net.IP, mask net.IPMask, v4Type, v6Type int, v4MaskType, v6MaskType int) {
86 ipType := v4Type
87 maskType := v4MaskType
88
89 encodeMask := mask
90 if mask == nil {
91 encodeMask = net.CIDRMask(32, 32)
92 }
93 v4IP := ip.To4()
94 if v4IP == nil {
95 ipType = v6Type
96 maskType = v6MaskType
97 if mask == nil {
98 encodeMask = net.CIDRMask(128, 128)
99 }
100 } else {
101 ip = v4IP
102 }
103
104 parent.AddRtAttr(ipType, ip)
105 parent.AddRtAttr(maskType, encodeMask)
106 }
107
108 func (filter *Flower) encode(parent *nl.RtAttr) error {
109 if filter.EthType != 0 {
110 parent.AddRtAttr(nl.TCA_FLOWER_KEY_ETH_TYPE, htons(filter.EthType))
111 }
112 if filter.SrcIP != nil {
113 filter.encodeIP(parent, filter.SrcIP, filter.SrcIPMask,
114 nl.TCA_FLOWER_KEY_IPV4_SRC, nl.TCA_FLOWER_KEY_IPV6_SRC,
115 nl.TCA_FLOWER_KEY_IPV4_SRC_MASK, nl.TCA_FLOWER_KEY_IPV6_SRC_MASK)
116 }
117 if filter.DestIP != nil {
118 filter.encodeIP(parent, filter.DestIP, filter.DestIPMask,
119 nl.TCA_FLOWER_KEY_IPV4_DST, nl.TCA_FLOWER_KEY_IPV6_DST,
120 nl.TCA_FLOWER_KEY_IPV4_DST_MASK, nl.TCA_FLOWER_KEY_IPV6_DST_MASK)
121 }
122 if filter.EncSrcIP != nil {
123 filter.encodeIP(parent, filter.EncSrcIP, filter.EncSrcIPMask,
124 nl.TCA_FLOWER_KEY_ENC_IPV4_SRC, nl.TCA_FLOWER_KEY_ENC_IPV6_SRC,
125 nl.TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK, nl.TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK)
126 }
127 if filter.EncDestIP != nil {
128 filter.encodeIP(parent, filter.EncDestIP, filter.EncSrcIPMask,
129 nl.TCA_FLOWER_KEY_ENC_IPV4_DST, nl.TCA_FLOWER_KEY_ENC_IPV6_DST,
130 nl.TCA_FLOWER_KEY_ENC_IPV4_DST_MASK, nl.TCA_FLOWER_KEY_ENC_IPV6_DST_MASK)
131 }
132 if filter.EncDestPort != 0 {
133 parent.AddRtAttr(nl.TCA_FLOWER_KEY_ENC_UDP_DST_PORT, htons(filter.EncDestPort))
134 }
135 if filter.EncKeyId != 0 {
136 parent.AddRtAttr(nl.TCA_FLOWER_KEY_ENC_KEY_ID, htonl(filter.EncKeyId))
137 }
138 if filter.IPProto != nil {
139 ipproto := *filter.IPProto
140 parent.AddRtAttr(nl.TCA_FLOWER_KEY_IP_PROTO, ipproto.Serialize())
141 if filter.SrcPort != 0 {
142 switch ipproto {
143 case nl.IPPROTO_TCP:
144 parent.AddRtAttr(nl.TCA_FLOWER_KEY_TCP_SRC, htons(filter.SrcPort))
145 case nl.IPPROTO_UDP:
146 parent.AddRtAttr(nl.TCA_FLOWER_KEY_UDP_SRC, htons(filter.SrcPort))
147 case nl.IPPROTO_SCTP:
148 parent.AddRtAttr(nl.TCA_FLOWER_KEY_SCTP_SRC, htons(filter.SrcPort))
149 }
150 }
151 if filter.DestPort != 0 {
152 switch ipproto {
153 case nl.IPPROTO_TCP:
154 parent.AddRtAttr(nl.TCA_FLOWER_KEY_TCP_DST, htons(filter.DestPort))
155 case nl.IPPROTO_UDP:
156 parent.AddRtAttr(nl.TCA_FLOWER_KEY_UDP_DST, htons(filter.DestPort))
157 case nl.IPPROTO_SCTP:
158 parent.AddRtAttr(nl.TCA_FLOWER_KEY_SCTP_DST, htons(filter.DestPort))
159 }
160 }
161 }
162
163 var flags uint32 = 0
164 if filter.SkipHw {
165 flags |= nl.TCA_CLS_FLAGS_SKIP_HW
166 }
167 if filter.SkipSw {
168 flags |= nl.TCA_CLS_FLAGS_SKIP_SW
169 }
170 parent.AddRtAttr(nl.TCA_FLOWER_FLAGS, htonl(flags))
171
172 actionsAttr := parent.AddRtAttr(nl.TCA_FLOWER_ACT, nil)
173 if err := EncodeActions(actionsAttr, filter.Actions); err != nil {
174 return err
175 }
176 return nil
177 }
178
179 func (filter *Flower) decode(data []syscall.NetlinkRouteAttr) error {
180 for _, datum := range data {
181 switch datum.Attr.Type {
182 case nl.TCA_FLOWER_KEY_ETH_TYPE:
183 filter.EthType = ntohs(datum.Value)
184 case nl.TCA_FLOWER_KEY_IPV4_SRC, nl.TCA_FLOWER_KEY_IPV6_SRC:
185 filter.SrcIP = datum.Value
186 case nl.TCA_FLOWER_KEY_IPV4_SRC_MASK, nl.TCA_FLOWER_KEY_IPV6_SRC_MASK:
187 filter.SrcIPMask = datum.Value
188 case nl.TCA_FLOWER_KEY_IPV4_DST, nl.TCA_FLOWER_KEY_IPV6_DST:
189 filter.DestIP = datum.Value
190 case nl.TCA_FLOWER_KEY_IPV4_DST_MASK, nl.TCA_FLOWER_KEY_IPV6_DST_MASK:
191 filter.DestIPMask = datum.Value
192 case nl.TCA_FLOWER_KEY_ENC_IPV4_SRC, nl.TCA_FLOWER_KEY_ENC_IPV6_SRC:
193 filter.EncSrcIP = datum.Value
194 case nl.TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK, nl.TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK:
195 filter.EncSrcIPMask = datum.Value
196 case nl.TCA_FLOWER_KEY_ENC_IPV4_DST, nl.TCA_FLOWER_KEY_ENC_IPV6_DST:
197 filter.EncDestIP = datum.Value
198 case nl.TCA_FLOWER_KEY_ENC_IPV4_DST_MASK, nl.TCA_FLOWER_KEY_ENC_IPV6_DST_MASK:
199 filter.EncDestIPMask = datum.Value
200 case nl.TCA_FLOWER_KEY_ENC_UDP_DST_PORT:
201 filter.EncDestPort = ntohs(datum.Value)
202 case nl.TCA_FLOWER_KEY_ENC_KEY_ID:
203 filter.EncKeyId = ntohl(datum.Value)
204 case nl.TCA_FLOWER_KEY_IP_PROTO:
205 val := new(nl.IPProto)
206 *val = nl.IPProto(datum.Value[0])
207 filter.IPProto = val
208 case nl.TCA_FLOWER_KEY_TCP_SRC, nl.TCA_FLOWER_KEY_UDP_SRC, nl.TCA_FLOWER_KEY_SCTP_SRC:
209 filter.SrcPort = ntohs(datum.Value)
210 case nl.TCA_FLOWER_KEY_TCP_DST, nl.TCA_FLOWER_KEY_UDP_DST, nl.TCA_FLOWER_KEY_SCTP_DST:
211 filter.DestPort = ntohs(datum.Value)
212 case nl.TCA_FLOWER_ACT:
213 tables, err := nl.ParseRouteAttr(datum.Value)
214 if err != nil {
215 return err
216 }
217 filter.Actions, err = parseActions(tables)
218 if err != nil {
219 return err
220 }
221 case nl.TCA_FLOWER_FLAGS:
222 attr := nl.DeserializeUint32Bitfield(datum.Value)
223 skipSw := attr.Value & nl.TCA_CLS_FLAGS_SKIP_HW
224 skipHw := attr.Value & nl.TCA_CLS_FLAGS_SKIP_SW
225 if skipSw != 0 {
226 filter.SkipSw = true
227 }
228 if skipHw != 0 {
229 filter.SkipHw = true
230 }
231 }
232 }
233 return nil
234 }
235
236
237
238 func FilterDel(filter Filter) error {
239 return pkgHandle.FilterDel(filter)
240 }
241
242
243
244 func (h *Handle) FilterDel(filter Filter) error {
245 return h.filterModify(filter, unix.RTM_DELTFILTER, 0)
246 }
247
248
249
250 func FilterAdd(filter Filter) error {
251 return pkgHandle.FilterAdd(filter)
252 }
253
254
255
256 func (h *Handle) FilterAdd(filter Filter) error {
257 return h.filterModify(filter, unix.RTM_NEWTFILTER, unix.NLM_F_CREATE|unix.NLM_F_EXCL)
258 }
259
260
261
262 func FilterReplace(filter Filter) error {
263 return pkgHandle.FilterReplace(filter)
264 }
265
266
267
268 func (h *Handle) FilterReplace(filter Filter) error {
269 return h.filterModify(filter, unix.RTM_NEWTFILTER, unix.NLM_F_CREATE)
270 }
271
272 func (h *Handle) filterModify(filter Filter, proto, flags int) error {
273 req := h.newNetlinkRequest(proto, flags|unix.NLM_F_ACK)
274 base := filter.Attrs()
275 msg := &nl.TcMsg{
276 Family: nl.FAMILY_ALL,
277 Ifindex: int32(base.LinkIndex),
278 Handle: base.Handle,
279 Parent: base.Parent,
280 Info: MakeHandle(base.Priority, nl.Swap16(base.Protocol)),
281 }
282 req.AddData(msg)
283 if filter.Attrs().Chain != nil {
284 req.AddData(nl.NewRtAttr(nl.TCA_CHAIN, nl.Uint32Attr(*filter.Attrs().Chain)))
285 }
286 req.AddData(nl.NewRtAttr(nl.TCA_KIND, nl.ZeroTerminated(filter.Type())))
287
288 options := nl.NewRtAttr(nl.TCA_OPTIONS, nil)
289
290 switch filter := filter.(type) {
291 case *U32:
292 sel := filter.Sel
293 if sel == nil {
294
295 sel = &nl.TcU32Sel{
296 Nkeys: 1,
297 Flags: nl.TC_U32_TERMINAL,
298 }
299 sel.Keys = append(sel.Keys, nl.TcU32Key{})
300 }
301
302 if native != networkOrder {
303
304 cSel := *sel
305 keys := make([]nl.TcU32Key, cap(sel.Keys))
306 copy(keys, sel.Keys)
307 cSel.Keys = keys
308 sel = &cSel
309
310
311 sel.Offmask = native.Uint16(htons(sel.Offmask))
312 sel.Hmask = native.Uint32(htonl(sel.Hmask))
313 for i, key := range sel.Keys {
314 sel.Keys[i].Mask = native.Uint32(htonl(key.Mask))
315 sel.Keys[i].Val = native.Uint32(htonl(key.Val))
316 }
317 }
318 sel.Nkeys = uint8(len(sel.Keys))
319 options.AddRtAttr(nl.TCA_U32_SEL, sel.Serialize())
320 if filter.ClassId != 0 {
321 options.AddRtAttr(nl.TCA_U32_CLASSID, nl.Uint32Attr(filter.ClassId))
322 }
323 if filter.Divisor != 0 {
324 if (filter.Divisor-1)&filter.Divisor != 0 {
325 return fmt.Errorf("illegal divisor %d. Must be a power of 2", filter.Divisor)
326 }
327 options.AddRtAttr(nl.TCA_U32_DIVISOR, nl.Uint32Attr(filter.Divisor))
328 }
329 if filter.Hash != 0 {
330 options.AddRtAttr(nl.TCA_U32_HASH, nl.Uint32Attr(filter.Hash))
331 }
332 if filter.Link != 0 {
333 options.AddRtAttr(nl.TCA_U32_LINK, nl.Uint32Attr(filter.Link))
334 }
335 if filter.Police != nil {
336 police := options.AddRtAttr(nl.TCA_U32_POLICE, nil)
337 if err := encodePolice(police, filter.Police); err != nil {
338 return err
339 }
340 }
341 actionsAttr := options.AddRtAttr(nl.TCA_U32_ACT, nil)
342
343 if filter.RedirIndex != 0 {
344 filter.Actions = append([]Action{NewMirredAction(filter.RedirIndex)}, filter.Actions...)
345 }
346 if err := EncodeActions(actionsAttr, filter.Actions); err != nil {
347 return err
348 }
349 case *FwFilter:
350 if filter.Mask != 0 {
351 b := make([]byte, 4)
352 native.PutUint32(b, filter.Mask)
353 options.AddRtAttr(nl.TCA_FW_MASK, b)
354 }
355 if filter.InDev != "" {
356 options.AddRtAttr(nl.TCA_FW_INDEV, nl.ZeroTerminated(filter.InDev))
357 }
358 if filter.Police != nil {
359 police := options.AddRtAttr(nl.TCA_FW_POLICE, nil)
360 if err := encodePolice(police, filter.Police); err != nil {
361 return err
362 }
363 }
364 if filter.ClassId != 0 {
365 b := make([]byte, 4)
366 native.PutUint32(b, filter.ClassId)
367 options.AddRtAttr(nl.TCA_FW_CLASSID, b)
368 }
369 actionsAttr := options.AddRtAttr(nl.TCA_FW_ACT, nil)
370 if err := EncodeActions(actionsAttr, filter.Actions); err != nil {
371 return err
372 }
373 case *BpfFilter:
374 var bpfFlags uint32
375 if filter.ClassId != 0 {
376 options.AddRtAttr(nl.TCA_BPF_CLASSID, nl.Uint32Attr(filter.ClassId))
377 }
378 if filter.Fd >= 0 {
379 options.AddRtAttr(nl.TCA_BPF_FD, nl.Uint32Attr((uint32(filter.Fd))))
380 }
381 if filter.Name != "" {
382 options.AddRtAttr(nl.TCA_BPF_NAME, nl.ZeroTerminated(filter.Name))
383 }
384 if filter.DirectAction {
385 bpfFlags |= nl.TCA_BPF_FLAG_ACT_DIRECT
386 }
387 options.AddRtAttr(nl.TCA_BPF_FLAGS, nl.Uint32Attr(bpfFlags))
388 case *MatchAll:
389 actionsAttr := options.AddRtAttr(nl.TCA_MATCHALL_ACT, nil)
390 if err := EncodeActions(actionsAttr, filter.Actions); err != nil {
391 return err
392 }
393 if filter.ClassId != 0 {
394 options.AddRtAttr(nl.TCA_MATCHALL_CLASSID, nl.Uint32Attr(filter.ClassId))
395 }
396 case *Flower:
397 if err := filter.encode(options); err != nil {
398 return err
399 }
400 }
401 req.AddData(options)
402 _, err := req.Execute(unix.NETLINK_ROUTE, 0)
403 return err
404 }
405
406
407
408
409 func FilterList(link Link, parent uint32) ([]Filter, error) {
410 return pkgHandle.FilterList(link, parent)
411 }
412
413
414
415
416 func (h *Handle) FilterList(link Link, parent uint32) ([]Filter, error) {
417 req := h.newNetlinkRequest(unix.RTM_GETTFILTER, unix.NLM_F_DUMP)
418 msg := &nl.TcMsg{
419 Family: nl.FAMILY_ALL,
420 Parent: parent,
421 }
422 if link != nil {
423 base := link.Attrs()
424 h.ensureIndex(base)
425 msg.Ifindex = int32(base.Index)
426 }
427 req.AddData(msg)
428
429 msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWTFILTER)
430 if err != nil {
431 return nil, err
432 }
433
434 var res []Filter
435 for _, m := range msgs {
436 msg := nl.DeserializeTcMsg(m)
437
438 attrs, err := nl.ParseRouteAttr(m[msg.Len():])
439 if err != nil {
440 return nil, err
441 }
442
443 base := FilterAttrs{
444 LinkIndex: int(msg.Ifindex),
445 Handle: msg.Handle,
446 Parent: msg.Parent,
447 }
448 base.Priority, base.Protocol = MajorMinor(msg.Info)
449 base.Protocol = nl.Swap16(base.Protocol)
450
451 var filter Filter
452 filterType := ""
453 detailed := false
454 for _, attr := range attrs {
455 switch attr.Attr.Type {
456 case nl.TCA_KIND:
457 filterType = string(attr.Value[:len(attr.Value)-1])
458 switch filterType {
459 case "u32":
460 filter = &U32{}
461 case "fw":
462 filter = &FwFilter{}
463 case "bpf":
464 filter = &BpfFilter{}
465 case "matchall":
466 filter = &MatchAll{}
467 case "flower":
468 filter = &Flower{}
469 default:
470 filter = &GenericFilter{FilterType: filterType}
471 }
472 case nl.TCA_OPTIONS:
473 data, err := nl.ParseRouteAttr(attr.Value)
474 if err != nil {
475 return nil, err
476 }
477 switch filterType {
478 case "u32":
479 detailed, err = parseU32Data(filter, data)
480 if err != nil {
481 return nil, err
482 }
483 case "fw":
484 detailed, err = parseFwData(filter, data)
485 if err != nil {
486 return nil, err
487 }
488 case "bpf":
489 detailed, err = parseBpfData(filter, data)
490 if err != nil {
491 return nil, err
492 }
493 case "matchall":
494 detailed, err = parseMatchAllData(filter, data)
495 if err != nil {
496 return nil, err
497 }
498 case "flower":
499 detailed, err = parseFlowerData(filter, data)
500 if err != nil {
501 return nil, err
502 }
503 default:
504 detailed = true
505 }
506 case nl.TCA_CHAIN:
507 val := new(uint32)
508 *val = native.Uint32(attr.Value)
509 base.Chain = val
510 }
511 }
512
513 if detailed {
514 *filter.Attrs() = base
515 res = append(res, filter)
516 }
517 }
518
519 return res, nil
520 }
521
522 func toTcGen(attrs *ActionAttrs, tcgen *nl.TcGen) {
523 tcgen.Index = uint32(attrs.Index)
524 tcgen.Capab = uint32(attrs.Capab)
525 tcgen.Action = int32(attrs.Action)
526 tcgen.Refcnt = int32(attrs.Refcnt)
527 tcgen.Bindcnt = int32(attrs.Bindcnt)
528 }
529
530 func toAttrs(tcgen *nl.TcGen, attrs *ActionAttrs) {
531 attrs.Index = int(tcgen.Index)
532 attrs.Capab = int(tcgen.Capab)
533 attrs.Action = TcAct(tcgen.Action)
534 attrs.Refcnt = int(tcgen.Refcnt)
535 attrs.Bindcnt = int(tcgen.Bindcnt)
536 }
537
538 func toTimeStamp(tcf *nl.Tcf) *ActionTimestamp {
539 return &ActionTimestamp{
540 Installed: tcf.Install,
541 LastUsed: tcf.LastUse,
542 Expires: tcf.Expires,
543 FirstUsed: tcf.FirstUse}
544 }
545
546 func encodePolice(attr *nl.RtAttr, action *PoliceAction) error {
547 var rtab [256]uint32
548 var ptab [256]uint32
549 police := nl.TcPolice{}
550 police.Index = uint32(action.Attrs().Index)
551 police.Bindcnt = int32(action.Attrs().Bindcnt)
552 police.Capab = uint32(action.Attrs().Capab)
553 police.Refcnt = int32(action.Attrs().Refcnt)
554 police.Rate.Rate = action.Rate
555 police.PeakRate.Rate = action.PeakRate
556 police.Action = int32(action.ExceedAction)
557
558 if police.Rate.Rate != 0 {
559 police.Rate.Mpu = action.Mpu
560 police.Rate.Overhead = action.Overhead
561 if CalcRtable(&police.Rate, rtab[:], action.RCellLog, action.Mtu, action.LinkLayer) < 0 {
562 return errors.New("TBF: failed to calculate rate table")
563 }
564 police.Burst = Xmittime(uint64(police.Rate.Rate), action.Burst)
565 }
566
567 police.Mtu = action.Mtu
568 if police.PeakRate.Rate != 0 {
569 police.PeakRate.Mpu = action.Mpu
570 police.PeakRate.Overhead = action.Overhead
571 if CalcRtable(&police.PeakRate, ptab[:], action.PCellLog, action.Mtu, action.LinkLayer) < 0 {
572 return errors.New("POLICE: failed to calculate peak rate table")
573 }
574 }
575
576 attr.AddRtAttr(nl.TCA_POLICE_TBF, police.Serialize())
577 if police.Rate.Rate != 0 {
578 attr.AddRtAttr(nl.TCA_POLICE_RATE, SerializeRtab(rtab))
579 }
580 if police.PeakRate.Rate != 0 {
581 attr.AddRtAttr(nl.TCA_POLICE_PEAKRATE, SerializeRtab(ptab))
582 }
583 if action.AvRate != 0 {
584 attr.AddRtAttr(nl.TCA_POLICE_AVRATE, nl.Uint32Attr(action.AvRate))
585 }
586 if action.NotExceedAction != 0 {
587 attr.AddRtAttr(nl.TCA_POLICE_RESULT, nl.Uint32Attr(uint32(action.NotExceedAction)))
588 }
589
590 return nil
591 }
592
593 func EncodeActions(attr *nl.RtAttr, actions []Action) error {
594 tabIndex := int(nl.TCA_ACT_TAB)
595
596 for _, action := range actions {
597 switch action := action.(type) {
598 default:
599 return fmt.Errorf("unknown action type %s", action.Type())
600 case *PoliceAction:
601 table := attr.AddRtAttr(tabIndex, nil)
602 tabIndex++
603 table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("police"))
604 aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil)
605 if err := encodePolice(aopts, action); err != nil {
606 return err
607 }
608 case *MirredAction:
609 table := attr.AddRtAttr(tabIndex, nil)
610 tabIndex++
611 table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("mirred"))
612 aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil)
613 mirred := nl.TcMirred{
614 Eaction: int32(action.MirredAction),
615 Ifindex: uint32(action.Ifindex),
616 }
617 toTcGen(action.Attrs(), &mirred.TcGen)
618 aopts.AddRtAttr(nl.TCA_MIRRED_PARMS, mirred.Serialize())
619 case *TunnelKeyAction:
620 table := attr.AddRtAttr(tabIndex, nil)
621 tabIndex++
622 table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("tunnel_key"))
623 aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil)
624 tun := nl.TcTunnelKey{
625 Action: int32(action.Action),
626 }
627 toTcGen(action.Attrs(), &tun.TcGen)
628 aopts.AddRtAttr(nl.TCA_TUNNEL_KEY_PARMS, tun.Serialize())
629 if action.Action == TCA_TUNNEL_KEY_SET {
630 aopts.AddRtAttr(nl.TCA_TUNNEL_KEY_ENC_KEY_ID, htonl(action.KeyID))
631 if v4 := action.SrcAddr.To4(); v4 != nil {
632 aopts.AddRtAttr(nl.TCA_TUNNEL_KEY_ENC_IPV4_SRC, v4[:])
633 } else if v6 := action.SrcAddr.To16(); v6 != nil {
634 aopts.AddRtAttr(nl.TCA_TUNNEL_KEY_ENC_IPV6_SRC, v6[:])
635 } else {
636 return fmt.Errorf("invalid src addr %s for tunnel_key action", action.SrcAddr)
637 }
638 if v4 := action.DstAddr.To4(); v4 != nil {
639 aopts.AddRtAttr(nl.TCA_TUNNEL_KEY_ENC_IPV4_DST, v4[:])
640 } else if v6 := action.DstAddr.To16(); v6 != nil {
641 aopts.AddRtAttr(nl.TCA_TUNNEL_KEY_ENC_IPV6_DST, v6[:])
642 } else {
643 return fmt.Errorf("invalid dst addr %s for tunnel_key action", action.DstAddr)
644 }
645 if action.DestPort != 0 {
646 aopts.AddRtAttr(nl.TCA_TUNNEL_KEY_ENC_DST_PORT, htons(action.DestPort))
647 }
648 }
649 case *SkbEditAction:
650 table := attr.AddRtAttr(tabIndex, nil)
651 tabIndex++
652 table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("skbedit"))
653 aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil)
654 skbedit := nl.TcSkbEdit{}
655 toTcGen(action.Attrs(), &skbedit.TcGen)
656 aopts.AddRtAttr(nl.TCA_SKBEDIT_PARMS, skbedit.Serialize())
657 if action.QueueMapping != nil {
658 aopts.AddRtAttr(nl.TCA_SKBEDIT_QUEUE_MAPPING, nl.Uint16Attr(*action.QueueMapping))
659 }
660 if action.Priority != nil {
661 aopts.AddRtAttr(nl.TCA_SKBEDIT_PRIORITY, nl.Uint32Attr(*action.Priority))
662 }
663 if action.PType != nil {
664 aopts.AddRtAttr(nl.TCA_SKBEDIT_PTYPE, nl.Uint16Attr(*action.PType))
665 }
666 if action.Mark != nil {
667 aopts.AddRtAttr(nl.TCA_SKBEDIT_MARK, nl.Uint32Attr(*action.Mark))
668 }
669 if action.Mask != nil {
670 aopts.AddRtAttr(nl.TCA_SKBEDIT_MASK, nl.Uint32Attr(*action.Mask))
671 }
672 case *ConnmarkAction:
673 table := attr.AddRtAttr(tabIndex, nil)
674 tabIndex++
675 table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("connmark"))
676 aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil)
677 connmark := nl.TcConnmark{
678 Zone: action.Zone,
679 }
680 toTcGen(action.Attrs(), &connmark.TcGen)
681 aopts.AddRtAttr(nl.TCA_CONNMARK_PARMS, connmark.Serialize())
682 case *CsumAction:
683 table := attr.AddRtAttr(tabIndex, nil)
684 tabIndex++
685 table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("csum"))
686 aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil)
687 csum := nl.TcCsum{
688 UpdateFlags: uint32(action.UpdateFlags),
689 }
690 toTcGen(action.Attrs(), &csum.TcGen)
691 aopts.AddRtAttr(nl.TCA_CSUM_PARMS, csum.Serialize())
692 case *BpfAction:
693 table := attr.AddRtAttr(tabIndex, nil)
694 tabIndex++
695 table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("bpf"))
696 aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil)
697 gen := nl.TcGen{}
698 toTcGen(action.Attrs(), &gen)
699 aopts.AddRtAttr(nl.TCA_ACT_BPF_PARMS, gen.Serialize())
700 aopts.AddRtAttr(nl.TCA_ACT_BPF_FD, nl.Uint32Attr(uint32(action.Fd)))
701 aopts.AddRtAttr(nl.TCA_ACT_BPF_NAME, nl.ZeroTerminated(action.Name))
702 case *GenericAction:
703 table := attr.AddRtAttr(tabIndex, nil)
704 tabIndex++
705 table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("gact"))
706 aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil)
707 gen := nl.TcGen{}
708 toTcGen(action.Attrs(), &gen)
709 aopts.AddRtAttr(nl.TCA_GACT_PARMS, gen.Serialize())
710 case *PeditAction:
711 table := attr.AddRtAttr(tabIndex, nil)
712 tabIndex++
713 pedit := nl.TcPedit{}
714 if action.SrcMacAddr != nil {
715 pedit.SetEthSrc(action.SrcMacAddr)
716 }
717 if action.DstMacAddr != nil {
718 pedit.SetEthDst(action.DstMacAddr)
719 }
720 if action.SrcIP != nil {
721 pedit.SetSrcIP(action.SrcIP)
722 }
723 if action.DstIP != nil {
724 pedit.SetDstIP(action.DstIP)
725 }
726 if action.SrcPort != 0 {
727 pedit.SetSrcPort(action.SrcPort, action.Proto)
728 }
729 if action.DstPort != 0 {
730 pedit.SetDstPort(action.DstPort, action.Proto)
731 }
732 pedit.Encode(table)
733 }
734 }
735 return nil
736 }
737
738 func parsePolice(data syscall.NetlinkRouteAttr, police *PoliceAction) {
739 switch data.Attr.Type {
740 case nl.TCA_POLICE_RESULT:
741 police.NotExceedAction = TcPolAct(native.Uint32(data.Value[0:4]))
742 case nl.TCA_POLICE_AVRATE:
743 police.AvRate = native.Uint32(data.Value[0:4])
744 case nl.TCA_POLICE_TBF:
745 p := *nl.DeserializeTcPolice(data.Value)
746 police.ActionAttrs = ActionAttrs{}
747 police.Attrs().Index = int(p.Index)
748 police.Attrs().Bindcnt = int(p.Bindcnt)
749 police.Attrs().Capab = int(p.Capab)
750 police.Attrs().Refcnt = int(p.Refcnt)
751 police.ExceedAction = TcPolAct(p.Action)
752 police.Rate = p.Rate.Rate
753 police.PeakRate = p.PeakRate.Rate
754 police.Burst = Xmitsize(uint64(p.Rate.Rate), p.Burst)
755 police.Mtu = p.Mtu
756 police.LinkLayer = int(p.Rate.Linklayer) & nl.TC_LINKLAYER_MASK
757 police.Overhead = p.Rate.Overhead
758 }
759 }
760
761 func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
762 var actions []Action
763 for _, table := range tables {
764 var action Action
765 var actionType string
766 var actionnStatistic *ActionStatistic
767 var actionTimestamp *ActionTimestamp
768 aattrs, err := nl.ParseRouteAttr(table.Value)
769 if err != nil {
770 return nil, err
771 }
772 nextattr:
773 for _, aattr := range aattrs {
774 switch aattr.Attr.Type {
775 case nl.TCA_KIND:
776 actionType = string(aattr.Value[:len(aattr.Value)-1])
777
778 switch actionType {
779 case "mirred":
780 action = &MirredAction{}
781 case "bpf":
782 action = &BpfAction{}
783 case "connmark":
784 action = &ConnmarkAction{}
785 case "csum":
786 action = &CsumAction{}
787 case "gact":
788 action = &GenericAction{}
789 case "tunnel_key":
790 action = &TunnelKeyAction{}
791 case "skbedit":
792 action = &SkbEditAction{}
793 case "police":
794 action = &PoliceAction{}
795 case "pedit":
796 action = &PeditAction{}
797 default:
798 break nextattr
799 }
800 case nl.TCA_OPTIONS:
801 adata, err := nl.ParseRouteAttr(aattr.Value)
802 if err != nil {
803 return nil, err
804 }
805 for _, adatum := range adata {
806 switch actionType {
807 case "mirred":
808 switch adatum.Attr.Type {
809 case nl.TCA_MIRRED_PARMS:
810 mirred := *nl.DeserializeTcMirred(adatum.Value)
811 action.(*MirredAction).ActionAttrs = ActionAttrs{}
812 toAttrs(&mirred.TcGen, action.Attrs())
813 action.(*MirredAction).Ifindex = int(mirred.Ifindex)
814 action.(*MirredAction).MirredAction = MirredAct(mirred.Eaction)
815 case nl.TCA_MIRRED_TM:
816 tcTs := nl.DeserializeTcf(adatum.Value)
817 actionTimestamp = toTimeStamp(tcTs)
818 }
819
820 case "tunnel_key":
821 switch adatum.Attr.Type {
822 case nl.TCA_TUNNEL_KEY_PARMS:
823 tun := *nl.DeserializeTunnelKey(adatum.Value)
824 action.(*TunnelKeyAction).ActionAttrs = ActionAttrs{}
825 toAttrs(&tun.TcGen, action.Attrs())
826 action.(*TunnelKeyAction).Action = TunnelKeyAct(tun.Action)
827 case nl.TCA_TUNNEL_KEY_ENC_KEY_ID:
828 action.(*TunnelKeyAction).KeyID = networkOrder.Uint32(adatum.Value[0:4])
829 case nl.TCA_TUNNEL_KEY_ENC_IPV6_SRC, nl.TCA_TUNNEL_KEY_ENC_IPV4_SRC:
830 action.(*TunnelKeyAction).SrcAddr = adatum.Value[:]
831 case nl.TCA_TUNNEL_KEY_ENC_IPV6_DST, nl.TCA_TUNNEL_KEY_ENC_IPV4_DST:
832 action.(*TunnelKeyAction).DstAddr = adatum.Value[:]
833 case nl.TCA_TUNNEL_KEY_ENC_DST_PORT:
834 action.(*TunnelKeyAction).DestPort = ntohs(adatum.Value)
835 case nl.TCA_TUNNEL_KEY_TM:
836 tcTs := nl.DeserializeTcf(adatum.Value)
837 actionTimestamp = toTimeStamp(tcTs)
838 }
839 case "skbedit":
840 switch adatum.Attr.Type {
841 case nl.TCA_SKBEDIT_PARMS:
842 skbedit := *nl.DeserializeSkbEdit(adatum.Value)
843 action.(*SkbEditAction).ActionAttrs = ActionAttrs{}
844 toAttrs(&skbedit.TcGen, action.Attrs())
845 case nl.TCA_SKBEDIT_MARK:
846 mark := native.Uint32(adatum.Value[0:4])
847 action.(*SkbEditAction).Mark = &mark
848 case nl.TCA_SKBEDIT_MASK:
849 mask := native.Uint32(adatum.Value[0:4])
850 action.(*SkbEditAction).Mask = &mask
851 case nl.TCA_SKBEDIT_PRIORITY:
852 priority := native.Uint32(adatum.Value[0:4])
853 action.(*SkbEditAction).Priority = &priority
854 case nl.TCA_SKBEDIT_PTYPE:
855 ptype := native.Uint16(adatum.Value[0:2])
856 action.(*SkbEditAction).PType = &ptype
857 case nl.TCA_SKBEDIT_QUEUE_MAPPING:
858 mapping := native.Uint16(adatum.Value[0:2])
859 action.(*SkbEditAction).QueueMapping = &mapping
860 case nl.TCA_SKBEDIT_TM:
861 tcTs := nl.DeserializeTcf(adatum.Value)
862 actionTimestamp = toTimeStamp(tcTs)
863 }
864 case "bpf":
865 switch adatum.Attr.Type {
866 case nl.TCA_ACT_BPF_PARMS:
867 gen := *nl.DeserializeTcGen(adatum.Value)
868 toAttrs(&gen, action.Attrs())
869 case nl.TCA_ACT_BPF_FD:
870 action.(*BpfAction).Fd = int(native.Uint32(adatum.Value[0:4]))
871 case nl.TCA_ACT_BPF_NAME:
872 action.(*BpfAction).Name = string(adatum.Value[:len(adatum.Value)-1])
873 case nl.TCA_ACT_BPF_TM:
874 tcTs := nl.DeserializeTcf(adatum.Value)
875 actionTimestamp = toTimeStamp(tcTs)
876 }
877 case "connmark":
878 switch adatum.Attr.Type {
879 case nl.TCA_CONNMARK_PARMS:
880 connmark := *nl.DeserializeTcConnmark(adatum.Value)
881 action.(*ConnmarkAction).ActionAttrs = ActionAttrs{}
882 toAttrs(&connmark.TcGen, action.Attrs())
883 action.(*ConnmarkAction).Zone = connmark.Zone
884 case nl.TCA_CONNMARK_TM:
885 tcTs := nl.DeserializeTcf(adatum.Value)
886 actionTimestamp = toTimeStamp(tcTs)
887 }
888 case "csum":
889 switch adatum.Attr.Type {
890 case nl.TCA_CSUM_PARMS:
891 csum := *nl.DeserializeTcCsum(adatum.Value)
892 action.(*CsumAction).ActionAttrs = ActionAttrs{}
893 toAttrs(&csum.TcGen, action.Attrs())
894 action.(*CsumAction).UpdateFlags = CsumUpdateFlags(csum.UpdateFlags)
895 case nl.TCA_CSUM_TM:
896 tcTs := nl.DeserializeTcf(adatum.Value)
897 actionTimestamp = toTimeStamp(tcTs)
898 }
899 case "gact":
900 switch adatum.Attr.Type {
901 case nl.TCA_GACT_PARMS:
902 gen := *nl.DeserializeTcGen(adatum.Value)
903 toAttrs(&gen, action.Attrs())
904 if action.Attrs().Action.String() == "goto" {
905 action.(*GenericAction).Chain = TC_ACT_EXT_VAL_MASK & gen.Action
906 }
907 case nl.TCA_GACT_TM:
908 tcTs := nl.DeserializeTcf(adatum.Value)
909 actionTimestamp = toTimeStamp(tcTs)
910 }
911 case "police":
912 parsePolice(adatum, action.(*PoliceAction))
913 }
914 }
915 case nl.TCA_ACT_STATS:
916 s, err := parseTcStats2(aattr.Value)
917 if err != nil {
918 return nil, err
919 }
920 actionnStatistic = (*ActionStatistic)(s)
921 }
922 }
923 action.Attrs().Statistics = actionnStatistic
924 action.Attrs().Timestamp = actionTimestamp
925 actions = append(actions, action)
926 }
927 return actions, nil
928 }
929
930 func parseU32Data(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) {
931 u32 := filter.(*U32)
932 detailed := false
933 for _, datum := range data {
934 switch datum.Attr.Type {
935 case nl.TCA_U32_SEL:
936 detailed = true
937 sel := nl.DeserializeTcU32Sel(datum.Value)
938 u32.Sel = sel
939 if native != networkOrder {
940
941 u32.Sel.Offmask = native.Uint16(htons(sel.Offmask))
942 u32.Sel.Hmask = native.Uint32(htonl(sel.Hmask))
943 for i, key := range u32.Sel.Keys {
944 u32.Sel.Keys[i].Mask = native.Uint32(htonl(key.Mask))
945 u32.Sel.Keys[i].Val = native.Uint32(htonl(key.Val))
946 }
947 }
948 case nl.TCA_U32_ACT:
949 tables, err := nl.ParseRouteAttr(datum.Value)
950 if err != nil {
951 return detailed, err
952 }
953 u32.Actions, err = parseActions(tables)
954 if err != nil {
955 return detailed, err
956 }
957 for _, action := range u32.Actions {
958 if action, ok := action.(*MirredAction); ok {
959 u32.RedirIndex = int(action.Ifindex)
960 }
961 }
962 case nl.TCA_U32_POLICE:
963 var police PoliceAction
964 adata, _ := nl.ParseRouteAttr(datum.Value)
965 for _, aattr := range adata {
966 parsePolice(aattr, &police)
967 }
968 u32.Police = &police
969 case nl.TCA_U32_CLASSID:
970 u32.ClassId = native.Uint32(datum.Value)
971 case nl.TCA_U32_DIVISOR:
972 u32.Divisor = native.Uint32(datum.Value)
973 case nl.TCA_U32_HASH:
974 u32.Hash = native.Uint32(datum.Value)
975 case nl.TCA_U32_LINK:
976 u32.Link = native.Uint32(datum.Value)
977 }
978 }
979 return detailed, nil
980 }
981
982 func parseFwData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) {
983 fw := filter.(*FwFilter)
984 detailed := true
985 for _, datum := range data {
986 switch datum.Attr.Type {
987 case nl.TCA_FW_MASK:
988 fw.Mask = native.Uint32(datum.Value[0:4])
989 case nl.TCA_FW_CLASSID:
990 fw.ClassId = native.Uint32(datum.Value[0:4])
991 case nl.TCA_FW_INDEV:
992 fw.InDev = string(datum.Value[:len(datum.Value)-1])
993 case nl.TCA_FW_POLICE:
994 var police PoliceAction
995 adata, _ := nl.ParseRouteAttr(datum.Value)
996 for _, aattr := range adata {
997 parsePolice(aattr, &police)
998 }
999 fw.Police = &police
1000 case nl.TCA_FW_ACT:
1001 tables, err := nl.ParseRouteAttr(datum.Value)
1002 if err != nil {
1003 return detailed, err
1004 }
1005 fw.Actions, err = parseActions(tables)
1006 if err != nil {
1007 return detailed, err
1008 }
1009 }
1010 }
1011 return detailed, nil
1012 }
1013
1014 func parseBpfData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) {
1015 bpf := filter.(*BpfFilter)
1016 detailed := true
1017 for _, datum := range data {
1018 switch datum.Attr.Type {
1019 case nl.TCA_BPF_FD:
1020 bpf.Fd = int(native.Uint32(datum.Value[0:4]))
1021 case nl.TCA_BPF_NAME:
1022 bpf.Name = string(datum.Value[:len(datum.Value)-1])
1023 case nl.TCA_BPF_CLASSID:
1024 bpf.ClassId = native.Uint32(datum.Value[0:4])
1025 case nl.TCA_BPF_FLAGS:
1026 flags := native.Uint32(datum.Value[0:4])
1027 if (flags & nl.TCA_BPF_FLAG_ACT_DIRECT) != 0 {
1028 bpf.DirectAction = true
1029 }
1030 case nl.TCA_BPF_ID:
1031 bpf.Id = int(native.Uint32(datum.Value[0:4]))
1032 case nl.TCA_BPF_TAG:
1033 bpf.Tag = hex.EncodeToString(datum.Value)
1034 }
1035 }
1036 return detailed, nil
1037 }
1038
1039 func parseMatchAllData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) {
1040 matchall := filter.(*MatchAll)
1041 detailed := true
1042 for _, datum := range data {
1043 switch datum.Attr.Type {
1044 case nl.TCA_MATCHALL_CLASSID:
1045 matchall.ClassId = native.Uint32(datum.Value[0:4])
1046 case nl.TCA_MATCHALL_ACT:
1047 tables, err := nl.ParseRouteAttr(datum.Value)
1048 if err != nil {
1049 return detailed, err
1050 }
1051 matchall.Actions, err = parseActions(tables)
1052 if err != nil {
1053 return detailed, err
1054 }
1055 }
1056 }
1057 return detailed, nil
1058 }
1059
1060 func parseFlowerData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) {
1061 return true, filter.(*Flower).decode(data)
1062 }
1063
1064 func AlignToAtm(size uint) uint {
1065 var linksize, cells int
1066 cells = int(size / nl.ATM_CELL_PAYLOAD)
1067 if (size % nl.ATM_CELL_PAYLOAD) > 0 {
1068 cells++
1069 }
1070 linksize = cells * nl.ATM_CELL_SIZE
1071 return uint(linksize)
1072 }
1073
1074 func AdjustSize(sz uint, mpu uint, linklayer int) uint {
1075 if sz < mpu {
1076 sz = mpu
1077 }
1078 switch linklayer {
1079 case nl.LINKLAYER_ATM:
1080 return AlignToAtm(sz)
1081 default:
1082 return sz
1083 }
1084 }
1085
1086 func CalcRtable(rate *nl.TcRateSpec, rtab []uint32, cellLog int, mtu uint32, linklayer int) int {
1087 bps := rate.Rate
1088 mpu := rate.Mpu
1089 var sz uint
1090 if mtu == 0 {
1091 mtu = 2047
1092 }
1093 if cellLog < 0 {
1094 cellLog = 0
1095 for (mtu >> uint(cellLog)) > 255 {
1096 cellLog++
1097 }
1098 }
1099 for i := 0; i < 256; i++ {
1100 sz = AdjustSize(uint((i+1)<<uint32(cellLog)), uint(mpu), linklayer)
1101 rtab[i] = Xmittime(uint64(bps), uint32(sz))
1102 }
1103 rate.CellAlign = -1
1104 rate.CellLog = uint8(cellLog)
1105 rate.Linklayer = uint8(linklayer & nl.TC_LINKLAYER_MASK)
1106 return cellLog
1107 }
1108
1109 func DeserializeRtab(b []byte) [256]uint32 {
1110 var rtab [256]uint32
1111 r := bytes.NewReader(b)
1112 _ = binary.Read(r, native, &rtab)
1113 return rtab
1114 }
1115
1116 func SerializeRtab(rtab [256]uint32) []byte {
1117 var w bytes.Buffer
1118 _ = binary.Write(&w, native, rtab)
1119 return w.Bytes()
1120 }
1121
View as plain text