Allow a Police to be specified directly on a U32 filter

This commit is contained in:
Christian Worm Mortensen 2024-04-08 13:52:04 +02:00 committed by Alessandro Boch
parent 99ce943af8
commit f4e6e3d5d5
2 changed files with 116 additions and 0 deletions

View File

@ -41,6 +41,7 @@ type U32 struct {
RedirIndex int RedirIndex int
Sel *TcU32Sel Sel *TcU32Sel
Actions []Action Actions []Action
Police *PoliceAction
} }
func (filter *U32) Attrs() *FilterAttrs { func (filter *U32) Attrs() *FilterAttrs {
@ -331,6 +332,12 @@ func (h *Handle) filterModify(filter Filter, proto, flags int) error {
if filter.Link != 0 { if filter.Link != 0 {
options.AddRtAttr(nl.TCA_U32_LINK, nl.Uint32Attr(filter.Link)) options.AddRtAttr(nl.TCA_U32_LINK, nl.Uint32Attr(filter.Link))
} }
if filter.Police != nil {
police := options.AddRtAttr(nl.TCA_U32_POLICE, nil)
if err := encodePolice(police, filter.Police); err != nil {
return err
}
}
actionsAttr := options.AddRtAttr(nl.TCA_U32_ACT, nil) actionsAttr := options.AddRtAttr(nl.TCA_U32_ACT, nil)
// backwards compatibility // backwards compatibility
if filter.RedirIndex != 0 { if filter.RedirIndex != 0 {
@ -952,6 +959,13 @@ func parseU32Data(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error)
u32.RedirIndex = int(action.Ifindex) u32.RedirIndex = int(action.Ifindex)
} }
} }
case nl.TCA_U32_POLICE:
var police PoliceAction
adata, _ := nl.ParseRouteAttr(datum.Value)
for _, aattr := range adata {
parsePolice(aattr, &police)
}
u32.Police = &police
case nl.TCA_U32_CLASSID: case nl.TCA_U32_CLASSID:
u32.ClassId = native.Uint32(datum.Value) u32.ClassId = native.Uint32(datum.Value)
case nl.TCA_U32_DIVISOR: case nl.TCA_U32_DIVISOR:

View File

@ -2276,6 +2276,108 @@ func TestFilterU32PoliceAddDel(t *testing.T) {
} }
} }
func TestFilterU32DirectPoliceAddDel(t *testing.T) {
tearDown := setUpNetlinkTest(t)
defer tearDown()
if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil {
t.Fatal(err)
}
link, err := LinkByName("foo")
if err != nil {
t.Fatal(err)
}
if err := LinkSetUp(link); err != nil {
t.Fatal(err)
}
qdisc := &Ingress{
QdiscAttrs: QdiscAttrs{
LinkIndex: link.Attrs().Index,
Handle: MakeHandle(0xffff, 0),
Parent: HANDLE_INGRESS,
},
}
if err := QdiscAdd(qdisc); err != nil {
t.Fatal(err)
}
const (
policeRate = 0x40000000 // 1 Gbps
policeBurst = 0x19000 // 100 KB
policePeakRate = 0x4000 // 16 Kbps
)
police := NewPoliceAction()
police.Rate = policeRate
police.PeakRate = policePeakRate
police.Burst = policeBurst
police.ExceedAction = TC_POLICE_SHOT
police.NotExceedAction = TC_POLICE_UNSPEC
classId := MakeHandle(1, 1)
filter := &U32{
FilterAttrs: FilterAttrs{
LinkIndex: link.Attrs().Index,
Parent: MakeHandle(0xffff, 0),
Priority: 1,
Protocol: unix.ETH_P_ALL,
},
ClassId: classId,
Police: police,
}
if err := FilterAdd(filter); err != nil {
t.Fatal(err)
}
filters, err := FilterList(link, MakeHandle(0xffff, 0))
if err != nil {
t.Fatal(err)
}
if len(filters) != 1 {
t.Fatal("Failed to add filter")
}
u32, ok := filters[0].(*U32)
if !ok {
t.Fatal("Filter is the wrong type")
}
if u32.Police == nil {
t.Fatalf("No police in filter")
}
if u32.Police.Rate != policeRate {
t.Fatal("Filter Rate doesn't match")
}
if u32.Police.PeakRate != policePeakRate {
t.Fatal("Filter PeakRate doesn't match")
}
if u32.Police.LinkLayer != nl.LINKLAYER_ETHERNET {
t.Fatal("Filter LinkLayer doesn't match")
}
if err := QdiscDel(qdisc); err != nil {
t.Fatal(err)
}
qdiscs, err := SafeQdiscList(link)
if err != nil {
t.Fatal(err)
}
found := false
for _, v := range qdiscs {
if _, ok := v.(*Ingress); ok {
found = true
break
}
}
if found {
t.Fatal("Failed to remove qdisc")
}
}
func TestFilterChainAddDel(t *testing.T) { func TestFilterChainAddDel(t *testing.T) {
tearDown := setUpNetlinkTest(t) tearDown := setUpNetlinkTest(t)
defer tearDown() defer tearDown()