Allow replacing filters

Add a function FilterReplace, which mirrors the behaviour of
QdiscReplace, etc. This makes it possible to swap out filters
with a single netlink message.
This commit is contained in:
Lorenz Bauer 2019-06-10 18:30:35 +01:00 committed by Alessandro Boch
parent 99a56c251a
commit a8241965b5
2 changed files with 78 additions and 1 deletions

View File

@ -151,8 +151,24 @@ func FilterAdd(filter Filter) error {
// FilterAdd will add a filter to the system.
// Equivalent to: `tc filter add $filter`
func (h *Handle) FilterAdd(filter Filter) error {
return h.filterModify(filter, unix.NLM_F_CREATE|unix.NLM_F_EXCL)
}
// FilterReplace will replace a filter.
// Equivalent to: `tc filter replace $filter`
func FilterReplace(filter Filter) error {
return pkgHandle.FilterReplace(filter)
}
// FilterReplace will replace a filter.
// Equivalent to: `tc filter replace $filter`
func (h *Handle) FilterReplace(filter Filter) error {
return h.filterModify(filter, unix.NLM_F_CREATE)
}
func (h *Handle) filterModify(filter Filter, flags int) error {
native = nl.NativeEndian()
req := h.newNetlinkRequest(unix.RTM_NEWTFILTER, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK)
req := h.newNetlinkRequest(unix.RTM_NEWTFILTER, flags|unix.NLM_F_ACK)
base := filter.Attrs()
msg := &nl.TcMsg{
Family: nl.FAMILY_ALL,

View File

@ -103,6 +103,67 @@ func TestFilterAddDel(t *testing.T) {
}
}
func TestFilterReplace(t *testing.T) {
tearDown := setUpNetlinkTest(t)
defer tearDown()
if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil {
t.Fatal(err)
}
if err := LinkAdd(&Ifb{LinkAttrs{Name: "bar"}}); err != nil {
t.Fatal(err)
}
link, err := LinkByName("foo")
if err != nil {
t.Fatal(err)
}
if err := LinkSetUp(link); err != nil {
t.Fatal(err)
}
redir, err := LinkByName("bar")
if err != nil {
t.Fatal(err)
}
if err := LinkSetUp(redir); 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)
}
filter := &U32{
FilterAttrs: FilterAttrs{
LinkIndex: link.Attrs().Index,
Parent: MakeHandle(0xffff, 0),
Priority: 1,
Protocol: unix.ETH_P_IP,
},
RedirIndex: redir.Attrs().Index,
ClassId: MakeHandle(1, 1),
}
if err := FilterReplace(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 replace filter")
}
if err := FilterReplace(filter); err != nil {
t.Fatal(err)
}
}
func TestAdvancedFilterAddDel(t *testing.T) {
tearDown := setUpNetlinkTest(t)
defer tearDown()