| 107 | } |
| 108 | |
| 109 | func (cc *Conn) AddFlowtable(f *Flowtable) *Flowtable { |
| 110 | cc.mu.Lock() |
| 111 | defer cc.mu.Unlock() |
| 112 | |
| 113 | data := cc.marshalAttr([]netlink.Attribute{ |
| 114 | {Type: NFTA_FLOWTABLE_TABLE, Data: []byte(f.Table.Name)}, |
| 115 | {Type: NFTA_FLOWTABLE_NAME, Data: []byte(f.Name)}, |
| 116 | {Type: NFTA_FLOWTABLE_FLAGS, Data: binaryutil.BigEndian.PutUint32(uint32(f.Flags))}, |
| 117 | }) |
| 118 | |
| 119 | if f.Hooknum == nil { |
| 120 | f.Hooknum = FlowtableHookIngress |
| 121 | } |
| 122 | |
| 123 | if f.Priority == nil { |
| 124 | f.Priority = FlowtablePriorityFilter |
| 125 | } |
| 126 | |
| 127 | hookAttr := []netlink.Attribute{ |
| 128 | {Type: NFTA_FLOWTABLE_HOOK_NUM, Data: binaryutil.BigEndian.PutUint32(uint32(*f.Hooknum))}, |
| 129 | {Type: NFTA_FLOWTABLE_PRIORITY, Data: binaryutil.BigEndian.PutUint32(uint32(*f.Priority))}, |
| 130 | } |
| 131 | if len(f.Devices) > 0 { |
| 132 | devs := make([]netlink.Attribute, len(f.Devices)) |
| 133 | for i, d := range f.Devices { |
| 134 | devs[i] = netlink.Attribute{Type: NFTA_DEVICE_NAME, Data: []byte(d)} |
| 135 | } |
| 136 | hookAttr = append(hookAttr, netlink.Attribute{ |
| 137 | Type: unix.NLA_F_NESTED | NFTA_FLOWTABLE_DEVS, |
| 138 | Data: cc.marshalAttr(devs), |
| 139 | }) |
| 140 | } |
| 141 | data = append(data, cc.marshalAttr([]netlink.Attribute{ |
| 142 | {Type: unix.NLA_F_NESTED | NFTA_FLOWTABLE_HOOK, Data: cc.marshalAttr(hookAttr)}, |
| 143 | })...) |
| 144 | |
| 145 | cc.messages = append(cc.messages, netlink.Message{ |
| 146 | Header: netlink.Header{ |
| 147 | Type: netlink.HeaderType((unix.NFNL_SUBSYS_NFTABLES << 8) | NFT_MSG_NEWFLOWTABLE), |
| 148 | Flags: netlink.Request | netlink.Acknowledge | netlink.Create, |
| 149 | }, |
| 150 | Data: append(extraHeader(uint8(f.Table.Family), 0), data...), |
| 151 | }) |
| 152 | |
| 153 | return f |
| 154 | } |
| 155 | |
| 156 | func (cc *Conn) DelFlowtable(f *Flowtable) { |
| 157 | cc.mu.Lock() |