Skip to content

Commit 1f910b7

Browse files
Mateusz Zalegaaboch
Mateusz Zalega
authored andcommitted
Support "sample" filter action
This change adds support for packet sampling using "psample" kernel module.
1 parent dc4f225 commit 1f910b7

File tree

4 files changed

+191
-0
lines changed

4 files changed

+191
-0
lines changed

filter.go

+23
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,29 @@ func NewPoliceAction() *PoliceAction {
398398
}
399399
}
400400

401+
type SampleAction struct {
402+
ActionAttrs
403+
Group uint32
404+
Rate uint32
405+
TruncSize uint32
406+
}
407+
408+
func (action *SampleAction) Type() string {
409+
return "sample"
410+
}
411+
412+
func (action *SampleAction) Attrs() *ActionAttrs {
413+
return &action.ActionAttrs
414+
}
415+
416+
func NewSampleAction() *SampleAction {
417+
return &SampleAction{
418+
ActionAttrs: ActionAttrs{
419+
Action: TC_ACT_PIPE,
420+
},
421+
}
422+
}
423+
401424
// MatchAll filters match all packets
402425
type MatchAll struct {
403426
FilterAttrs

filter_linux.go

+25
Original file line numberDiff line numberDiff line change
@@ -740,6 +740,17 @@ func EncodeActions(attr *nl.RtAttr, actions []Action) error {
740740
aopts.AddRtAttr(nl.TCA_ACT_BPF_PARMS, gen.Serialize())
741741
aopts.AddRtAttr(nl.TCA_ACT_BPF_FD, nl.Uint32Attr(uint32(action.Fd)))
742742
aopts.AddRtAttr(nl.TCA_ACT_BPF_NAME, nl.ZeroTerminated(action.Name))
743+
case *SampleAction:
744+
table := attr.AddRtAttr(tabIndex, nil)
745+
tabIndex++
746+
table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("sample"))
747+
aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil)
748+
gen := nl.TcGen{}
749+
toTcGen(action.Attrs(), &gen)
750+
aopts.AddRtAttr(nl.TCA_ACT_SAMPLE_PARMS, gen.Serialize())
751+
aopts.AddRtAttr(nl.TCA_ACT_SAMPLE_RATE, nl.Uint32Attr(action.Rate))
752+
aopts.AddRtAttr(nl.TCA_ACT_SAMPLE_PSAMPLE_GROUP, nl.Uint32Attr(action.Group))
753+
aopts.AddRtAttr(nl.TCA_ACT_SAMPLE_TRUNC_SIZE, nl.Uint32Attr(action.TruncSize))
743754
case *GenericAction:
744755
table := attr.AddRtAttr(tabIndex, nil)
745756
tabIndex++
@@ -826,6 +837,8 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
826837
action = &ConnmarkAction{}
827838
case "csum":
828839
action = &CsumAction{}
840+
case "sample":
841+
action = &SampleAction{}
829842
case "gact":
830843
action = &GenericAction{}
831844
case "vlan":
@@ -950,6 +963,18 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
950963
tcTs := nl.DeserializeTcf(adatum.Value)
951964
actionTimestamp = toTimeStamp(tcTs)
952965
}
966+
case "sample":
967+
switch adatum.Attr.Type {
968+
case nl.TCA_ACT_SAMPLE_PARMS:
969+
gen := *nl.DeserializeTcGen(adatum.Value)
970+
toAttrs(&gen, action.Attrs())
971+
case nl.TCA_ACT_SAMPLE_RATE:
972+
action.(*SampleAction).Rate = native.Uint32(adatum.Value[0:4])
973+
case nl.TCA_ACT_SAMPLE_PSAMPLE_GROUP:
974+
action.(*SampleAction).Group = native.Uint32(adatum.Value[0:4])
975+
case nl.TCA_ACT_SAMPLE_TRUNC_SIZE:
976+
action.(*SampleAction).TruncSize = native.Uint32(adatum.Value[0:4])
977+
}
953978
case "gact":
954979
switch adatum.Attr.Type {
955980
case nl.TCA_GACT_PARMS:

filter_test.go

+132
Original file line numberDiff line numberDiff line change
@@ -2599,3 +2599,135 @@ func TestFilterChainAddDel(t *testing.T) {
25992599
t.Fatal("Failed to remove qdisc")
26002600
}
26012601
}
2602+
2603+
func TestFilterSampleAddDel(t *testing.T) {
2604+
minKernelRequired(t, 4, 11)
2605+
if _, err := GenlFamilyGet("psample"); err != nil {
2606+
t.Skip("psample genetlink family unavailable - is CONFIG_PSAMPLE enabled?")
2607+
}
2608+
2609+
tearDown := setUpNetlinkTest(t)
2610+
defer tearDown()
2611+
if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil {
2612+
t.Fatal(err)
2613+
}
2614+
link, err := LinkByName("foo")
2615+
if err != nil {
2616+
t.Fatal(err)
2617+
}
2618+
if err := LinkSetUp(link); err != nil {
2619+
t.Fatal(err)
2620+
}
2621+
2622+
qdisc := &Ingress{
2623+
QdiscAttrs: QdiscAttrs{
2624+
LinkIndex: link.Attrs().Index,
2625+
Handle: MakeHandle(0xffff, 0),
2626+
Parent: HANDLE_INGRESS,
2627+
},
2628+
}
2629+
if err := QdiscAdd(qdisc); err != nil {
2630+
t.Fatal(err)
2631+
}
2632+
qdiscs, err := SafeQdiscList(link)
2633+
if err != nil {
2634+
t.Fatal(err)
2635+
}
2636+
2637+
found := false
2638+
for _, v := range qdiscs {
2639+
if _, ok := v.(*Ingress); ok {
2640+
found = true
2641+
break
2642+
}
2643+
}
2644+
if !found {
2645+
t.Fatal("Qdisc is the wrong type")
2646+
}
2647+
2648+
sample := NewSampleAction()
2649+
sample.Group = 7
2650+
sample.Rate = 12
2651+
sample.TruncSize = 200
2652+
2653+
classId := MakeHandle(1, 1)
2654+
filter := &MatchAll{
2655+
FilterAttrs: FilterAttrs{
2656+
LinkIndex: link.Attrs().Index,
2657+
Parent: MakeHandle(0xffff, 0),
2658+
Priority: 1,
2659+
Protocol: unix.ETH_P_ALL,
2660+
},
2661+
ClassId: classId,
2662+
Actions: []Action{
2663+
sample,
2664+
},
2665+
}
2666+
2667+
if err := FilterAdd(filter); err != nil {
2668+
t.Fatal(err)
2669+
}
2670+
2671+
filters, err := FilterList(link, MakeHandle(0xffff, 0))
2672+
if err != nil {
2673+
t.Fatal(err)
2674+
}
2675+
if len(filters) != 1 {
2676+
t.Fatal("Failed to add filter")
2677+
}
2678+
mf, ok := filters[0].(*MatchAll)
2679+
if !ok {
2680+
t.Fatal("Filter is the wrong type")
2681+
}
2682+
2683+
if len(mf.Actions) < 1 {
2684+
t.Fatalf("Too few Actions in filter")
2685+
}
2686+
if mf.ClassId != classId {
2687+
t.Fatalf("ClassId of the filter is the wrong value")
2688+
}
2689+
2690+
lsample, ok := mf.Actions[0].(*SampleAction)
2691+
if !ok {
2692+
t.Fatal("Unable to find sample action")
2693+
}
2694+
if lsample.Group != sample.Group {
2695+
t.Fatalf("Inconsistent sample action group")
2696+
}
2697+
if lsample.Rate != sample.Rate {
2698+
t.Fatalf("Inconsistent sample action rate")
2699+
}
2700+
if lsample.TruncSize != sample.TruncSize {
2701+
t.Fatalf("Inconsistent sample truncation size")
2702+
}
2703+
2704+
if err := FilterDel(filter); err != nil {
2705+
t.Fatal(err)
2706+
}
2707+
filters, err = FilterList(link, MakeHandle(0xffff, 0))
2708+
if err != nil {
2709+
t.Fatal(err)
2710+
}
2711+
if len(filters) != 0 {
2712+
t.Fatal("Failed to remove filter")
2713+
}
2714+
2715+
if err := QdiscDel(qdisc); err != nil {
2716+
t.Fatal(err)
2717+
}
2718+
qdiscs, err = SafeQdiscList(link)
2719+
if err != nil {
2720+
t.Fatal(err)
2721+
}
2722+
2723+
found = false
2724+
for _, v := range qdiscs {
2725+
if _, ok := v.(*Ingress); ok {
2726+
found = true
2727+
break
2728+
}
2729+
}
2730+
if found {
2731+
t.Fatal("Failed to remove qdisc")
2732+
}
2733+
}

nl/tc_linux.go

+11
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,17 @@ const (
7777
TCA_ACT_MAX
7878
)
7979

80+
const (
81+
TCA_ACT_SAMPLE_UNSPEC = iota
82+
TCA_ACT_SAMPLE_TM
83+
TCA_ACT_SAMPLE_PARMS
84+
TCA_ACT_SAMPLE_RATE
85+
TCA_ACT_SAMPLE_TRUNC_SIZE
86+
TCA_ACT_SAMPLE_PSAMPLE_GROUP
87+
TCA_ACT_SAMPLE_PAD
88+
TCA_ACT_SAMPLE_MAX
89+
)
90+
8091
const (
8192
TCA_PRIO_UNSPEC = iota
8293
TCA_PRIO_MQ

0 commit comments

Comments
 (0)