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