Skip to content

Commit

Permalink
filter: Add support for the csum action in u32
Browse files Browse the repository at this point in the history
This patch adds support for the U32 action that can force a csum
recalculation in different layers of a packet.
  • Loading branch information
niax authored and aboch committed Mar 29, 2022
1 parent 6bb6f8a commit 5cb84e4
Show file tree
Hide file tree
Showing 4 changed files with 213 additions and 0 deletions.
33 changes: 33 additions & 0 deletions filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,39 @@ func NewConnmarkAction() *ConnmarkAction {
}
}

type CsumUpdateFlags uint32

const (
TCA_CSUM_UPDATE_FLAG_IPV4HDR CsumUpdateFlags = 1
TCA_CSUM_UPDATE_FLAG_ICMP CsumUpdateFlags = 2
TCA_CSUM_UPDATE_FLAG_IGMP CsumUpdateFlags = 4
TCA_CSUM_UPDATE_FLAG_TCP CsumUpdateFlags = 8
TCA_CSUM_UPDATE_FLAG_UDP CsumUpdateFlags = 16
TCA_CSUM_UPDATE_FLAG_UDPLITE CsumUpdateFlags = 32
TCA_CSUM_UPDATE_FLAG_SCTP CsumUpdateFlags = 64
)

type CsumAction struct {
ActionAttrs
UpdateFlags CsumUpdateFlags
}

func (action *CsumAction) Type() string {
return "csum"
}

func (action *CsumAction) Attrs() *ActionAttrs {
return &action.ActionAttrs
}

func NewCsumAction() *CsumAction {
return &CsumAction{
ActionAttrs: ActionAttrs{
Action: TC_ACT_PIPE,
},
}
}

type MirredAct uint8

func (a MirredAct) String() string {
Expand Down
20 changes: 20 additions & 0 deletions filter_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -607,6 +607,16 @@ func EncodeActions(attr *nl.RtAttr, actions []Action) error {
}
toTcGen(action.Attrs(), &connmark.TcGen)
aopts.AddRtAttr(nl.TCA_CONNMARK_PARMS, connmark.Serialize())
case *CsumAction:
table := attr.AddRtAttr(tabIndex, nil)
tabIndex++
table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("csum"))
aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil)
csum := nl.TcCsum{
UpdateFlags: uint32(action.UpdateFlags),
}
toTcGen(action.Attrs(), &csum.TcGen)
aopts.AddRtAttr(nl.TCA_CSUM_PARMS, csum.Serialize())
case *BpfAction:
table := attr.AddRtAttr(tabIndex, nil)
tabIndex++
Expand Down Expand Up @@ -675,6 +685,8 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
action = &BpfAction{}
case "connmark":
action = &ConnmarkAction{}
case "csum":
action = &CsumAction{}
case "gact":
action = &GenericAction{}
case "tunnel_key":
Expand Down Expand Up @@ -755,6 +767,14 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
toAttrs(&connmark.TcGen, action.Attrs())
action.(*ConnmarkAction).Zone = connmark.Zone
}
case "csum":
switch adatum.Attr.Type {
case nl.TCA_CSUM_PARMS:
csum := *nl.DeserializeTcCsum(adatum.Value)
action.(*CsumAction).ActionAttrs = ActionAttrs{}
toAttrs(&csum.TcGen, action.Attrs())
action.(*CsumAction).UpdateFlags = CsumUpdateFlags(csum.UpdateFlags)
}
case "gact":
switch adatum.Attr.Type {
case nl.TCA_GACT_PARMS:
Expand Down
129 changes: 129 additions & 0 deletions filter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -785,6 +785,135 @@ func TestFilterU32ConnmarkAddDel(t *testing.T) {
}
}

func TestFilterU32CsumAddDel(t *testing.T) {
tearDown := setUpNetlinkTest(t)
defer tearDown()
if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil {
t.Fatalf("add link foo error: %v", err)
}
link, err := LinkByName("foo")
if err != nil {
t.Fatalf("add link foo error: %v", err)
}
if err := LinkSetUp(link); err != nil {
t.Fatalf("set foo link up error: %v", 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)
}
qdiscs, err := SafeQdiscList(link)
if err != nil {
t.Fatalf("get qdisc error: %v", err)
}

found := false
for _, v := range qdiscs {
if _, ok := v.(*Ingress); ok {
found = true
break
}
}
if !found {
t.Fatal("Qdisc is the wrong type")
}

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,
Actions: []Action{
&CsumAction{
ActionAttrs: ActionAttrs{
Action: TC_ACT_PIPE,
},
UpdateFlags: TCA_CSUM_UPDATE_FLAG_TCP,
},
},
}

if err := FilterAdd(filter); err != nil {
t.Fatal(err)
}

filters, err := FilterList(link, MakeHandle(0xffff, 0))
if err != nil {
t.Fatalf("get filter error: %v", err)
}

if len(filters) != 1 {
t.Fatalf("the count filters error, expect: 1, acutal: %d", len(filters))
}

ft, ok := filters[0].(*U32)
if !ok {
t.Fatal("Filter is the wrong type")
}

if ft.LinkIndex != link.Attrs().Index {
t.Fatal("link index error")
}

if len(ft.Actions) != 1 {
t.Fatalf("filter has wrong number of actions, expect: 1, acutal: %d", len(filters))
}

csum, ok := ft.Actions[0].(*CsumAction)
if !ok {
t.Fatal("action is the wrong type")
}

if csum.Attrs().Action != TC_ACT_PIPE {
t.Fatal("Csum action isn't TC_ACT_PIPE")
}

if csum.UpdateFlags != TCA_CSUM_UPDATE_FLAG_TCP {
t.Fatalf("Csum action isn't TCA_CSUM_UPDATE_FLAG_TCP, got %d", csum.UpdateFlags)
}

if err := FilterDel(ft); err != nil {
t.Fatal(err)
}
filters, err = FilterList(link, MakeHandle(0xffff, 0))
if err != nil {
t.Fatal(err)
}
if len(filters) != 0 {
t.Fatal("Failed to remove filter")
}

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 setupLinkForTestWithQdisc(t *testing.T, linkName string) (Qdisc, Link) {
if err := LinkAdd(&Ifb{LinkAttrs{Name: linkName}}); err != nil {
t.Fatal(err)
Expand Down
31 changes: 31 additions & 0 deletions nl/tc_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ const (
SizeofTcU32Sel = 0x10 // without keys
SizeofTcGen = 0x14
SizeofTcConnmark = SizeofTcGen + 0x04
SizeofTcCsum = SizeofTcGen + 0x04
SizeofTcMirred = SizeofTcGen + 0x08
SizeofTcTunnelKey = SizeofTcGen + 0x04
SizeofTcSkbEdit = SizeofTcGen
Expand Down Expand Up @@ -694,6 +695,36 @@ func (x *TcConnmark) Serialize() []byte {
return (*(*[SizeofTcConnmark]byte)(unsafe.Pointer(x)))[:]
}

const (
TCA_CSUM_UNSPEC = iota
TCA_CSUM_PARMS
TCA_CSUM_TM
TCA_CSUM_PAD
TCA_CSUM_MAX = TCA_CSUM_PAD
)

// struct tc_csum {
// tc_gen;
// __u32 update_flags;
// }

type TcCsum struct {
TcGen
UpdateFlags uint32
}

func (msg *TcCsum) Len() int {
return SizeofTcCsum
}

func DeserializeTcCsum(b []byte) *TcCsum {
return (*TcCsum)(unsafe.Pointer(&b[0:SizeofTcCsum][0]))
}

func (x *TcCsum) Serialize() []byte {
return (*(*[SizeofTcCsum]byte)(unsafe.Pointer(x)))[:]
}

const (
TCA_ACT_MIRRED = 8
)
Expand Down

0 comments on commit 5cb84e4

Please sign in to comment.