1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

Merge pull request #1200 from aboch/vndnl

Update netlink to 7995ff5
This commit is contained in:
Alessandro Boch 2016-06-01 10:23:41 -07:00
commit 2dd111e74c
7 changed files with 283 additions and 107 deletions

View file

@ -398,11 +398,11 @@
}, },
{ {
"ImportPath": "github.com/vishvananda/netlink", "ImportPath": "github.com/vishvananda/netlink",
"Rev": "b824519a9a33e5a757ba599209d66a34be8361b1" "Rev": "7995ff5647a22cbf0dc41bf5c0e977bdb0d5c6b7"
}, },
{ {
"ImportPath": "github.com/vishvananda/netlink/nl", "ImportPath": "github.com/vishvananda/netlink/nl",
"Rev": "b824519a9a33e5a757ba599209d66a34be8361b1" "Rev": "7995ff5647a22cbf0dc41bf5c0e977bdb0d5c6b7"
}, },
{ {
"ImportPath": "github.com/vishvananda/netns", "ImportPath": "github.com/vishvananda/netns",

View file

@ -3,6 +3,7 @@ package netlink
import ( import (
"errors" "errors"
"fmt" "fmt"
"github.com/vishvananda/netlink/nl" "github.com/vishvananda/netlink/nl"
) )
@ -26,13 +27,105 @@ func (q FilterAttrs) String() string {
return fmt.Sprintf("{LinkIndex: %d, Handle: %s, Parent: %s, Priority: %d, Protocol: %d}", q.LinkIndex, HandleStr(q.Handle), HandleStr(q.Parent), q.Priority, q.Protocol) return fmt.Sprintf("{LinkIndex: %d, Handle: %s, Parent: %s, Priority: %d, Protocol: %d}", q.LinkIndex, HandleStr(q.Handle), HandleStr(q.Parent), q.Priority, q.Protocol)
} }
type TcAct int32
const (
TC_ACT_UNSPEC TcAct = -1
TC_ACT_OK TcAct = 0
TC_ACT_RECLASSIFY TcAct = 1
TC_ACT_SHOT TcAct = 2
TC_ACT_PIPE TcAct = 3
TC_ACT_STOLEN TcAct = 4
TC_ACT_QUEUED TcAct = 5
TC_ACT_REPEAT TcAct = 6
TC_ACT_REDIRECT TcAct = 7
TC_ACT_JUMP TcAct = 0x10000000
)
func (a TcAct) String() string {
switch a {
case TC_ACT_UNSPEC:
return "unspec"
case TC_ACT_OK:
return "ok"
case TC_ACT_RECLASSIFY:
return "reclassify"
case TC_ACT_SHOT:
return "shot"
case TC_ACT_PIPE:
return "pipe"
case TC_ACT_STOLEN:
return "stolen"
case TC_ACT_QUEUED:
return "queued"
case TC_ACT_REPEAT:
return "repeat"
case TC_ACT_REDIRECT:
return "redirect"
case TC_ACT_JUMP:
return "jump"
}
return fmt.Sprintf("0x%x", a)
}
type TcPolAct int32
const (
TC_POLICE_UNSPEC TcPolAct = TcPolAct(TC_ACT_UNSPEC)
TC_POLICE_OK TcPolAct = TcPolAct(TC_ACT_OK)
TC_POLICE_RECLASSIFY TcPolAct = TcPolAct(TC_ACT_RECLASSIFY)
TC_POLICE_SHOT TcPolAct = TcPolAct(TC_ACT_SHOT)
TC_POLICE_PIPE TcPolAct = TcPolAct(TC_ACT_PIPE)
)
func (a TcPolAct) String() string {
switch a {
case TC_POLICE_UNSPEC:
return "unspec"
case TC_POLICE_OK:
return "ok"
case TC_POLICE_RECLASSIFY:
return "reclassify"
case TC_POLICE_SHOT:
return "shot"
case TC_POLICE_PIPE:
return "pipe"
}
return fmt.Sprintf("0x%x", a)
}
type ActionAttrs struct {
Index int
Capab int
Action TcAct
Refcnt int
Bindcnt int
}
func (q ActionAttrs) String() string {
return fmt.Sprintf("{Index: %d, Capab: %x, Action: %s, Refcnt: %d, Bindcnt: %d}", q.Index, q.Capab, q.Action.String(), q.Refcnt, q.Bindcnt)
}
// Action represents an action in any supported filter. // Action represents an action in any supported filter.
type Action interface { type Action interface {
Attrs() *ActionAttrs
Type() string Type() string
} }
type GenericAction struct {
ActionAttrs
}
func (action *GenericAction) Type() string {
return "generic"
}
func (action *GenericAction) Attrs() *ActionAttrs {
return &action.ActionAttrs
}
type BpfAction struct { type BpfAction struct {
nl.TcActBpf ActionAttrs
Fd int Fd int
Name string Name string
} }
@ -41,21 +134,54 @@ func (action *BpfAction) Type() string {
return "bpf" return "bpf"
} }
func (action *BpfAction) Attrs() *ActionAttrs {
return &action.ActionAttrs
}
type MirredAct uint8
func (a MirredAct) String() string {
switch a {
case TCA_EGRESS_REDIR:
return "egress redir"
case TCA_EGRESS_MIRROR:
return "egress mirror"
case TCA_INGRESS_REDIR:
return "ingress redir"
case TCA_INGRESS_MIRROR:
return "ingress mirror"
}
return "unknown"
}
const (
TCA_EGRESS_REDIR MirredAct = 1 /* packet redirect to EGRESS*/
TCA_EGRESS_MIRROR MirredAct = 2 /* mirror packet to EGRESS */
TCA_INGRESS_REDIR MirredAct = 3 /* packet redirect to INGRESS*/
TCA_INGRESS_MIRROR MirredAct = 4 /* mirror packet to INGRESS */
)
type MirredAction struct { type MirredAction struct {
nl.TcMirred ActionAttrs
MirredAction MirredAct
Ifindex int
} }
func (action *MirredAction) Type() string { func (action *MirredAction) Type() string {
return "mirred" return "mirred"
} }
func (action *MirredAction) Attrs() *ActionAttrs {
return &action.ActionAttrs
}
func NewMirredAction(redirIndex int) *MirredAction { func NewMirredAction(redirIndex int) *MirredAction {
return &MirredAction{ return &MirredAction{
TcMirred: nl.TcMirred{ ActionAttrs: ActionAttrs{
TcGen: nl.TcGen{Action: nl.TC_ACT_STOLEN}, Action: TC_ACT_STOLEN,
Eaction: nl.TCA_EGRESS_REDIR,
Ifindex: uint32(redirIndex),
}, },
MirredAction: TCA_EGRESS_REDIR,
Ifindex: redirIndex,
} }
} }
@ -86,7 +212,7 @@ type FilterFwAttrs struct {
Rate uint32 Rate uint32
AvRate uint32 AvRate uint32
PeakRate uint32 PeakRate uint32
Action int Action TcPolAct
Overhead uint16 Overhead uint16
LinkLayer int LinkLayer int
} }
@ -95,8 +221,9 @@ type FilterFwAttrs struct {
type Fw struct { type Fw struct {
FilterAttrs FilterAttrs
ClassId uint32 ClassId uint32
Police nl.TcPolice // TODO remove nl type from interface
InDev string Police nl.TcPolice
InDev string
// TODO Action // TODO Action
Mask uint32 Mask uint32
AvRate uint32 AvRate uint32

View file

@ -207,6 +207,8 @@ func (h *Handle) FilterList(link Link, parent uint32) ([]Filter, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
default:
detailed = true
} }
} }
} }
@ -220,6 +222,22 @@ func (h *Handle) FilterList(link Link, parent uint32) ([]Filter, error) {
return res, nil return res, nil
} }
func toTcGen(attrs *ActionAttrs, tcgen *nl.TcGen) {
tcgen.Index = uint32(attrs.Index)
tcgen.Capab = uint32(attrs.Capab)
tcgen.Action = int32(attrs.Action)
tcgen.Refcnt = int32(attrs.Refcnt)
tcgen.Bindcnt = int32(attrs.Bindcnt)
}
func toAttrs(tcgen *nl.TcGen, attrs *ActionAttrs) {
attrs.Index = int(tcgen.Index)
attrs.Capab = int(tcgen.Capab)
attrs.Action = TcAct(tcgen.Action)
attrs.Refcnt = int(tcgen.Refcnt)
attrs.Bindcnt = int(tcgen.Bindcnt)
}
func encodeActions(attr *nl.RtAttr, actions []Action) error { func encodeActions(attr *nl.RtAttr, actions []Action) error {
tabIndex := int(nl.TCA_ACT_TAB) tabIndex := int(nl.TCA_ACT_TAB)
@ -232,15 +250,30 @@ func encodeActions(attr *nl.RtAttr, actions []Action) error {
tabIndex++ tabIndex++
nl.NewRtAttrChild(table, nl.TCA_ACT_KIND, nl.ZeroTerminated("mirred")) nl.NewRtAttrChild(table, nl.TCA_ACT_KIND, nl.ZeroTerminated("mirred"))
aopts := nl.NewRtAttrChild(table, nl.TCA_ACT_OPTIONS, nil) aopts := nl.NewRtAttrChild(table, nl.TCA_ACT_OPTIONS, nil)
nl.NewRtAttrChild(aopts, nl.TCA_MIRRED_PARMS, action.Serialize()) mirred := nl.TcMirred{
Eaction: int32(action.MirredAction),
Ifindex: uint32(action.Ifindex),
}
toTcGen(action.Attrs(), &mirred.TcGen)
nl.NewRtAttrChild(aopts, nl.TCA_MIRRED_PARMS, mirred.Serialize())
case *BpfAction: case *BpfAction:
table := nl.NewRtAttrChild(attr, tabIndex, nil) table := nl.NewRtAttrChild(attr, tabIndex, nil)
tabIndex++ tabIndex++
nl.NewRtAttrChild(table, nl.TCA_ACT_KIND, nl.ZeroTerminated("bpf")) nl.NewRtAttrChild(table, nl.TCA_ACT_KIND, nl.ZeroTerminated("bpf"))
aopts := nl.NewRtAttrChild(table, nl.TCA_ACT_OPTIONS, nil) aopts := nl.NewRtAttrChild(table, nl.TCA_ACT_OPTIONS, nil)
nl.NewRtAttrChild(aopts, nl.TCA_ACT_BPF_PARMS, action.Serialize()) gen := nl.TcGen{}
toTcGen(action.Attrs(), &gen)
nl.NewRtAttrChild(aopts, nl.TCA_ACT_BPF_PARMS, gen.Serialize())
nl.NewRtAttrChild(aopts, nl.TCA_ACT_BPF_FD, nl.Uint32Attr(uint32(action.Fd))) nl.NewRtAttrChild(aopts, nl.TCA_ACT_BPF_FD, nl.Uint32Attr(uint32(action.Fd)))
nl.NewRtAttrChild(aopts, nl.TCA_ACT_BPF_NAME, nl.ZeroTerminated(action.Name)) nl.NewRtAttrChild(aopts, nl.TCA_ACT_BPF_NAME, nl.ZeroTerminated(action.Name))
case *GenericAction:
table := nl.NewRtAttrChild(attr, tabIndex, nil)
tabIndex++
nl.NewRtAttrChild(table, nl.TCA_ACT_KIND, nl.ZeroTerminated("gact"))
aopts := nl.NewRtAttrChild(table, nl.TCA_ACT_OPTIONS, nil)
gen := nl.TcGen{}
toTcGen(action.Attrs(), &gen)
nl.NewRtAttrChild(aopts, nl.TCA_GACT_PARMS, gen.Serialize())
} }
} }
return nil return nil
@ -266,6 +299,8 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
action = &MirredAction{} action = &MirredAction{}
case "bpf": case "bpf":
action = &BpfAction{} action = &BpfAction{}
case "gact":
action = &GenericAction{}
default: default:
break nextattr break nextattr
} }
@ -279,17 +314,28 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
case "mirred": case "mirred":
switch adatum.Attr.Type { switch adatum.Attr.Type {
case nl.TCA_MIRRED_PARMS: case nl.TCA_MIRRED_PARMS:
action.(*MirredAction).TcMirred = *nl.DeserializeTcMirred(adatum.Value) mirred := *nl.DeserializeTcMirred(adatum.Value)
toAttrs(&mirred.TcGen, action.Attrs())
action.(*MirredAction).ActionAttrs = ActionAttrs{}
action.(*MirredAction).Ifindex = int(mirred.Ifindex)
action.(*MirredAction).MirredAction = MirredAct(mirred.Eaction)
} }
case "bpf": case "bpf":
switch adatum.Attr.Type { switch adatum.Attr.Type {
case nl.TCA_ACT_BPF_PARMS: case nl.TCA_ACT_BPF_PARMS:
action.(*BpfAction).TcActBpf = *nl.DeserializeTcActBpf(adatum.Value) gen := *nl.DeserializeTcGen(adatum.Value)
toAttrs(&gen, action.Attrs())
case nl.TCA_ACT_BPF_FD: case nl.TCA_ACT_BPF_FD:
action.(*BpfAction).Fd = int(native.Uint32(adatum.Value[0:4])) action.(*BpfAction).Fd = int(native.Uint32(adatum.Value[0:4]))
case nl.TCA_ACT_BPF_NAME: case nl.TCA_ACT_BPF_NAME:
action.(*BpfAction).Name = string(adatum.Value[:len(adatum.Value)-1]) action.(*BpfAction).Name = string(adatum.Value[:len(adatum.Value)-1])
} }
case "gact":
switch adatum.Attr.Type {
case nl.TCA_GACT_PARMS:
gen := *nl.DeserializeTcGen(adatum.Value)
toAttrs(&gen, action.Attrs())
}
} }
} }
} }

View file

@ -380,6 +380,7 @@ func Subscribe(protocol int, groups ...uint) (*NetlinkSocket, error) {
func (s *NetlinkSocket) Close() { func (s *NetlinkSocket) Close() {
syscall.Close(s.fd) syscall.Close(s.fd)
s.fd = -1
} }
func (s *NetlinkSocket) GetFd() int { func (s *NetlinkSocket) GetFd() int {
@ -387,6 +388,9 @@ func (s *NetlinkSocket) GetFd() int {
} }
func (s *NetlinkSocket) Send(request *NetlinkRequest) error { func (s *NetlinkSocket) Send(request *NetlinkRequest) error {
if s.fd < 0 {
return fmt.Errorf("Send called on a closed socket")
}
if err := syscall.Sendto(s.fd, request.Serialize(), 0, &s.lsa); err != nil { if err := syscall.Sendto(s.fd, request.Serialize(), 0, &s.lsa); err != nil {
return err return err
} }
@ -394,6 +398,9 @@ func (s *NetlinkSocket) Send(request *NetlinkRequest) error {
} }
func (s *NetlinkSocket) Receive() ([]syscall.NetlinkMessage, error) { func (s *NetlinkSocket) Receive() ([]syscall.NetlinkMessage, error) {
if s.fd < 0 {
return nil, fmt.Errorf("Receive called on a closed socket")
}
rb := make([]byte, syscall.Getpagesize()) rb := make([]byte, syscall.Getpagesize())
nr, _, err := syscall.Recvfrom(s.fd, rb, 0) nr, _, err := syscall.Recvfrom(s.fd, rb, 0)
if err != nil { if err != nil {

View file

@ -78,8 +78,8 @@ const (
SizeofTcHtbGlob = 0x14 SizeofTcHtbGlob = 0x14
SizeofTcU32Key = 0x10 SizeofTcU32Key = 0x10
SizeofTcU32Sel = 0x10 // without keys SizeofTcU32Sel = 0x10 // without keys
SizeofTcActBpf = 0x14 SizeofTcGen = 0x14
SizeofTcMirred = 0x1c SizeofTcMirred = SizeofTcGen + 0x08
SizeofTcPolice = 2*SizeofTcRateSpec + 0x20 SizeofTcPolice = 2*SizeofTcRateSpec + 0x20
) )
@ -516,6 +516,81 @@ func (x *TcU32Sel) Serialize() []byte {
return buf return buf
} }
type TcGen struct {
Index uint32
Capab uint32
Action int32
Refcnt int32
Bindcnt int32
}
func (msg *TcGen) Len() int {
return SizeofTcGen
}
func DeserializeTcGen(b []byte) *TcGen {
return (*TcGen)(unsafe.Pointer(&b[0:SizeofTcGen][0]))
}
func (x *TcGen) Serialize() []byte {
return (*(*[SizeofTcGen]byte)(unsafe.Pointer(x)))[:]
}
// #define tc_gen \
// __u32 index; \
// __u32 capab; \
// int action; \
// int refcnt; \
// int bindcnt
const (
TCA_ACT_GACT = 5
)
const (
TCA_GACT_UNSPEC = iota
TCA_GACT_TM
TCA_GACT_PARMS
TCA_GACT_PROB
TCA_GACT_MAX = TCA_GACT_PROB
)
type TcGact TcGen
const (
TCA_ACT_BPF = 13
)
const (
TCA_ACT_BPF_UNSPEC = iota
TCA_ACT_BPF_TM
TCA_ACT_BPF_PARMS
TCA_ACT_BPF_OPS_LEN
TCA_ACT_BPF_OPS
TCA_ACT_BPF_FD
TCA_ACT_BPF_NAME
TCA_ACT_BPF_MAX = TCA_ACT_BPF_NAME
)
const (
TCA_BPF_FLAG_ACT_DIRECT uint32 = 1 << iota
)
const (
TCA_BPF_UNSPEC = iota
TCA_BPF_ACT
TCA_BPF_POLICE
TCA_BPF_CLASSID
TCA_BPF_OPS_LEN
TCA_BPF_OPS
TCA_BPF_FD
TCA_BPF_NAME
TCA_BPF_FLAGS
TCA_BPF_MAX = TCA_BPF_FLAGS
)
type TcBpf TcGen
const ( const (
TCA_ACT_MIRRED = 8 TCA_ACT_MIRRED = 8
) )
@ -527,56 +602,6 @@ const (
TCA_MIRRED_MAX = TCA_MIRRED_PARMS TCA_MIRRED_MAX = TCA_MIRRED_PARMS
) )
const (
TCA_EGRESS_REDIR = 1 /* packet redirect to EGRESS*/
TCA_EGRESS_MIRROR = 2 /* mirror packet to EGRESS */
TCA_INGRESS_REDIR = 3 /* packet redirect to INGRESS*/
TCA_INGRESS_MIRROR = 4 /* mirror packet to INGRESS */
)
const (
TC_ACT_UNSPEC = int32(-1)
TC_ACT_OK = 0
TC_ACT_RECLASSIFY = 1
TC_ACT_SHOT = 2
TC_ACT_PIPE = 3
TC_ACT_STOLEN = 4
TC_ACT_QUEUED = 5
TC_ACT_REPEAT = 6
TC_ACT_REDIRECT = 7
TC_ACT_JUMP = 0x10000000
)
type TcGen struct {
Index uint32
Capab uint32
Action int32
Refcnt int32
Bindcnt int32
}
type TcActBpf struct {
TcGen
}
func (msg *TcActBpf) Len() int {
return SizeofTcActBpf
}
func DeserializeTcActBpf(b []byte) *TcActBpf {
return (*TcActBpf)(unsafe.Pointer(&b[0:SizeofTcActBpf][0]))
}
func (x *TcActBpf) Serialize() []byte {
return (*(*[SizeofTcActBpf]byte)(unsafe.Pointer(x)))[:]
}
// #define tc_gen \
// __u32 index; \
// __u32 capab; \
// int action; \
// int refcnt; \
// int bindcnt
// struct tc_mirred { // struct tc_mirred {
// tc_gen; // tc_gen;
// int eaction; /* one of IN/EGRESS_MIRROR/REDIR */ // int eaction; /* one of IN/EGRESS_MIRROR/REDIR */
@ -601,14 +626,6 @@ func (x *TcMirred) Serialize() []byte {
return (*(*[SizeofTcMirred]byte)(unsafe.Pointer(x)))[:] return (*(*[SizeofTcMirred]byte)(unsafe.Pointer(x)))[:]
} }
const (
TC_POLICE_UNSPEC = TC_ACT_UNSPEC
TC_POLICE_OK = TC_ACT_OK
TC_POLICE_RECLASSIFY = TC_ACT_RECLASSIFY
TC_POLICE_SHOT = TC_ACT_SHOT
TC_POLICE_PIPE = TC_ACT_PIPE
)
// struct tc_police { // struct tc_police {
// __u32 index; // __u32 index;
// int action; // int action;
@ -656,31 +673,3 @@ const (
TCA_FW_MASK TCA_FW_MASK
TCA_FW_MAX = TCA_FW_MASK TCA_FW_MAX = TCA_FW_MASK
) )
const (
TCA_BPF_FLAG_ACT_DIRECT uint32 = 1 << iota
)
const (
TCA_BPF_UNSPEC = iota
TCA_BPF_ACT
TCA_BPF_POLICE
TCA_BPF_CLASSID
TCA_BPF_OPS_LEN
TCA_BPF_OPS
TCA_BPF_FD
TCA_BPF_NAME
TCA_BPF_FLAGS
TCA_BPF_MAX = TCA_BPF_FLAGS
)
const (
TCA_ACT_BPF_UNSPEC = iota
TCA_ACT_BPF_TM
TCA_ACT_BPF_PARMS
TCA_ACT_BPF_OPS_LEN
TCA_ACT_BPF_OPS
TCA_ACT_BPF_FD
TCA_ACT_BPF_NAME
TCA_ACT_BPF_MAX = TCA_ACT_BPF_NAME
)

View file

@ -43,12 +43,13 @@ type XfrmPolicyTmpl struct {
Src net.IP Src net.IP
Proto Proto Proto Proto
Mode Mode Mode Mode
Spi int
Reqid int Reqid int
} }
func (t XfrmPolicyTmpl) String() string { func (t XfrmPolicyTmpl) String() string {
return fmt.Sprintf("{Dst: %v, Src: %v, Proto: %s, Mode: %s, Reqid: 0x%x}", return fmt.Sprintf("{Dst: %v, Src: %v, Proto: %s, Mode: %s, Spi: 0x%x, Reqid: 0x%x}",
t.Dst, t.Src, t.Proto, t.Mode, t.Reqid) t.Dst, t.Src, t.Proto, t.Mode, t.Spi, t.Reqid)
} }
// XfrmPolicy represents an ipsec policy. It represents the overlay network // XfrmPolicy represents an ipsec policy. It represents the overlay network

View file

@ -22,8 +22,12 @@ func selFromPolicy(sel *nl.XfrmSelector, policy *XfrmPolicy) {
sel.Proto = uint8(policy.Proto) sel.Proto = uint8(policy.Proto)
sel.Dport = nl.Swap16(uint16(policy.DstPort)) sel.Dport = nl.Swap16(uint16(policy.DstPort))
sel.Sport = nl.Swap16(uint16(policy.SrcPort)) sel.Sport = nl.Swap16(uint16(policy.SrcPort))
sel.DportMask = ^uint16(0) if sel.Dport != 0 {
sel.SportMask = ^uint16(0) sel.DportMask = ^uint16(0)
}
if sel.Sport != 0 {
sel.SportMask = ^uint16(0)
}
} }
// XfrmPolicyAdd will add an xfrm policy to the system. // XfrmPolicyAdd will add an xfrm policy to the system.
@ -71,6 +75,7 @@ func (h *Handle) xfrmPolicyAddOrUpdate(policy *XfrmPolicy, nlProto int) error {
userTmpl.XfrmId.Daddr.FromIP(tmpl.Dst) userTmpl.XfrmId.Daddr.FromIP(tmpl.Dst)
userTmpl.Saddr.FromIP(tmpl.Src) userTmpl.Saddr.FromIP(tmpl.Src)
userTmpl.XfrmId.Proto = uint8(tmpl.Proto) userTmpl.XfrmId.Proto = uint8(tmpl.Proto)
userTmpl.XfrmId.Spi = nl.Swap32(uint32(tmpl.Spi))
userTmpl.Mode = uint8(tmpl.Mode) userTmpl.Mode = uint8(tmpl.Mode)
userTmpl.Reqid = uint32(tmpl.Reqid) userTmpl.Reqid = uint32(tmpl.Reqid)
userTmpl.Aalgos = ^uint32(0) userTmpl.Aalgos = ^uint32(0)
@ -236,6 +241,7 @@ func parseXfrmPolicy(m []byte, family int) (*XfrmPolicy, error) {
resTmpl.Src = tmpl.Saddr.ToIP() resTmpl.Src = tmpl.Saddr.ToIP()
resTmpl.Proto = Proto(tmpl.XfrmId.Proto) resTmpl.Proto = Proto(tmpl.XfrmId.Proto)
resTmpl.Mode = Mode(tmpl.Mode) resTmpl.Mode = Mode(tmpl.Mode)
resTmpl.Spi = int(nl.Swap32(tmpl.XfrmId.Spi))
resTmpl.Reqid = int(tmpl.Reqid) resTmpl.Reqid = int(tmpl.Reqid)
policy.Tmpls = append(policy.Tmpls, resTmpl) policy.Tmpls = append(policy.Tmpls, resTmpl)
} }