github.com/vishvananda/netlink@v1.3.1/bridge_linux.go (about) 1 package netlink 2 3 import ( 4 "errors" 5 "fmt" 6 "syscall" 7 8 "github.com/vishvananda/netlink/nl" 9 "golang.org/x/sys/unix" 10 ) 11 12 // BridgeVlanTunnelShow gets vlanid-tunnelid mapping. 13 // Equivalent to: `bridge vlan tunnelshow` 14 // 15 // If the returned error is [ErrDumpInterrupted], results may be inconsistent 16 // or incomplete. 17 func BridgeVlanTunnelShow() ([]nl.TunnelInfo, error) { 18 return pkgHandle.BridgeVlanTunnelShow() 19 } 20 21 func (h *Handle) BridgeVlanTunnelShow() ([]nl.TunnelInfo, error) { 22 req := h.newNetlinkRequest(unix.RTM_GETLINK, unix.NLM_F_DUMP) 23 msg := nl.NewIfInfomsg(unix.AF_BRIDGE) 24 req.AddData(msg) 25 req.AddData(nl.NewRtAttr(unix.IFLA_EXT_MASK, nl.Uint32Attr(uint32(nl.RTEXT_FILTER_BRVLAN)))) 26 27 msgs, executeErr := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWLINK) 28 if executeErr != nil && !errors.Is(executeErr, ErrDumpInterrupted) { 29 return nil, executeErr 30 } 31 ret := make([]nl.TunnelInfo, 0) 32 for _, m := range msgs { 33 msg := nl.DeserializeIfInfomsg(m) 34 35 attrs, err := nl.ParseRouteAttr(m[msg.Len():]) 36 if err != nil { 37 return nil, err 38 } 39 for _, attr := range attrs { 40 switch attr.Attr.Type { 41 case unix.IFLA_AF_SPEC: 42 nestedAttrs, err := nl.ParseRouteAttr(attr.Value) 43 if err != nil { 44 return nil, fmt.Errorf("failed to parse nested attr %v", err) 45 } 46 for _, nestAttr := range nestedAttrs { 47 switch nestAttr.Attr.Type { 48 case nl.IFLA_BRIDGE_VLAN_TUNNEL_INFO: 49 ret, err = parseTunnelInfo(&nestAttr, ret) 50 if err != nil { 51 return nil, fmt.Errorf("failed to parse tunnelinfo %v", err) 52 } 53 } 54 } 55 } 56 } 57 } 58 return ret, executeErr 59 } 60 61 func parseTunnelInfo(nestAttr *syscall.NetlinkRouteAttr, results []nl.TunnelInfo) ([]nl.TunnelInfo, error) { 62 tunnelInfos, err := nl.ParseRouteAttr(nestAttr.Value) 63 if err != nil { 64 return nil, fmt.Errorf("failed to parse nested attr %v", err) 65 } 66 var tunnelId uint32 67 var vid uint16 68 var flag uint16 69 for _, tunnelInfo := range tunnelInfos { 70 switch tunnelInfo.Attr.Type { 71 case nl.IFLA_BRIDGE_VLAN_TUNNEL_ID: 72 tunnelId = native.Uint32(tunnelInfo.Value) 73 case nl.IFLA_BRIDGE_VLAN_TUNNEL_VID: 74 vid = native.Uint16(tunnelInfo.Value) 75 case nl.IFLA_BRIDGE_VLAN_TUNNEL_FLAGS: 76 flag = native.Uint16(tunnelInfo.Value) 77 } 78 } 79 80 if flag == nl.BRIDGE_VLAN_INFO_RANGE_END { 81 lastTi := results[len(results)-1] 82 vni := lastTi.TunId + 1 83 for i := lastTi.Vid + 1; i < vid; i++ { 84 t := nl.TunnelInfo{ 85 TunId: vni, 86 Vid: i, 87 } 88 results = append(results, t) 89 vni++ 90 } 91 } 92 93 t := nl.TunnelInfo{ 94 TunId: tunnelId, 95 Vid: vid, 96 } 97 98 results = append(results, t) 99 return results, nil 100 } 101 102 // BridgeVlanList gets a map of device id to bridge vlan infos. 103 // Equivalent to: `bridge vlan show` 104 // 105 // If the returned error is [ErrDumpInterrupted], results may be inconsistent 106 // or incomplete. 107 func BridgeVlanList() (map[int32][]*nl.BridgeVlanInfo, error) { 108 return pkgHandle.BridgeVlanList() 109 } 110 111 // BridgeVlanList gets a map of device id to bridge vlan infos. 112 // Equivalent to: `bridge vlan show` 113 // 114 // If the returned error is [ErrDumpInterrupted], results may be inconsistent 115 // or incomplete. 116 func (h *Handle) BridgeVlanList() (map[int32][]*nl.BridgeVlanInfo, error) { 117 req := h.newNetlinkRequest(unix.RTM_GETLINK, unix.NLM_F_DUMP) 118 msg := nl.NewIfInfomsg(unix.AF_BRIDGE) 119 req.AddData(msg) 120 req.AddData(nl.NewRtAttr(unix.IFLA_EXT_MASK, nl.Uint32Attr(uint32(nl.RTEXT_FILTER_BRVLAN)))) 121 122 msgs, executeErr := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWLINK) 123 if executeErr != nil && !errors.Is(executeErr, ErrDumpInterrupted) { 124 return nil, executeErr 125 } 126 ret := make(map[int32][]*nl.BridgeVlanInfo) 127 for _, m := range msgs { 128 msg := nl.DeserializeIfInfomsg(m) 129 130 attrs, err := nl.ParseRouteAttr(m[msg.Len():]) 131 if err != nil { 132 return nil, err 133 } 134 for _, attr := range attrs { 135 switch attr.Attr.Type { 136 case unix.IFLA_AF_SPEC: 137 //nested attr 138 nestAttrs, err := nl.ParseRouteAttr(attr.Value) 139 if err != nil { 140 return nil, fmt.Errorf("failed to parse nested attr %v", err) 141 } 142 for _, nestAttr := range nestAttrs { 143 switch nestAttr.Attr.Type { 144 case nl.IFLA_BRIDGE_VLAN_INFO: 145 vlanInfo := nl.DeserializeBridgeVlanInfo(nestAttr.Value) 146 ret[msg.Index] = append(ret[msg.Index], vlanInfo) 147 } 148 } 149 } 150 } 151 } 152 return ret, executeErr 153 } 154 155 // BridgeVlanAddTunnelInfo adds a new vlan filter entry 156 // Equivalent to: `bridge vlan add dev DEV vid VID tunnel_info id TUNID [ self ] [ master ]` 157 func BridgeVlanAddTunnelInfo(link Link, vid uint16, tunid uint32, self, master bool) error { 158 return pkgHandle.BridgeVlanAddTunnelInfo(link, vid, 0, tunid, 0, self, master) 159 } 160 161 // BridgeVlanAddRangeTunnelInfoRange adds a new vlan filter entry 162 // Equivalent to: `bridge vlan add dev DEV vid VID-VIDEND tunnel_info id VIN-VINEND [ self ] [ master ]` 163 func BridgeVlanAddRangeTunnelInfoRange(link Link, vid, vidEnd uint16, tunid, tunidEnd uint32, self, master bool) error { 164 return pkgHandle.BridgeVlanAddTunnelInfo(link, vid, vidEnd, tunid, tunidEnd, self, master) 165 } 166 167 func (h *Handle) BridgeVlanAddTunnelInfo(link Link, vid, vidEnd uint16, tunid, tunidEnd uint32, self, master bool) error { 168 return h.bridgeVlanModify(unix.RTM_SETLINK, link, vid, vidEnd, tunid, tunidEnd, false, false, self, master) 169 } 170 171 // BridgeVlanDelTunnelInfo adds a new vlan filter entry 172 // Equivalent to: `bridge vlan del dev DEV vid VID tunnel_info id TUNID [ self ] [ master ]` 173 func BridgeVlanDelTunnelInfo(link Link, vid uint16, tunid uint32, self, master bool) error { 174 return pkgHandle.BridgeVlanDelTunnelInfo(link, vid, 0, tunid, 0, self, master) 175 } 176 177 // BridgeVlanDelRangeTunnelInfoRange adds a new vlan filter entry 178 // Equivalent to: `bridge vlan del dev DEV vid VID-VIDEND tunnel_info id VIN-VINEND [ self ] [ master ]` 179 func BridgeVlanDelRangeTunnelInfoRange(link Link, vid, vidEnd uint16, tunid, tunidEnd uint32, self, master bool) error { 180 return pkgHandle.BridgeVlanDelTunnelInfo(link, vid, vidEnd, tunid, tunidEnd, self, master) 181 } 182 183 func (h *Handle) BridgeVlanDelTunnelInfo(link Link, vid, vidEnd uint16, tunid, tunidEnd uint32, self, master bool) error { 184 return h.bridgeVlanModify(unix.RTM_DELLINK, link, vid, vidEnd, tunid, tunidEnd, false, false, self, master) 185 } 186 187 // BridgeVlanAdd adds a new vlan filter entry 188 // Equivalent to: `bridge vlan add dev DEV vid VID [ pvid ] [ untagged ] [ self ] [ master ]` 189 func BridgeVlanAdd(link Link, vid uint16, pvid, untagged, self, master bool) error { 190 return pkgHandle.BridgeVlanAdd(link, vid, pvid, untagged, self, master) 191 } 192 193 // BridgeVlanAdd adds a new vlan filter entry 194 // Equivalent to: `bridge vlan add dev DEV vid VID [ pvid ] [ untagged ] [ self ] [ master ]` 195 func (h *Handle) BridgeVlanAdd(link Link, vid uint16, pvid, untagged, self, master bool) error { 196 return h.bridgeVlanModify(unix.RTM_SETLINK, link, vid, 0, 0, 0, pvid, untagged, self, master) 197 } 198 199 // BridgeVlanAddRange adds a new vlan filter entry 200 // Equivalent to: `bridge vlan add dev DEV vid VID-VIDEND [ pvid ] [ untagged ] [ self ] [ master ]` 201 func BridgeVlanAddRange(link Link, vid, vidEnd uint16, pvid, untagged, self, master bool) error { 202 return pkgHandle.BridgeVlanAddRange(link, vid, vidEnd, pvid, untagged, self, master) 203 } 204 205 // BridgeVlanAddRange adds a new vlan filter entry 206 // Equivalent to: `bridge vlan add dev DEV vid VID-VIDEND [ pvid ] [ untagged ] [ self ] [ master ]` 207 func (h *Handle) BridgeVlanAddRange(link Link, vid, vidEnd uint16, pvid, untagged, self, master bool) error { 208 return h.bridgeVlanModify(unix.RTM_SETLINK, link, vid, vidEnd, 0, 0, pvid, untagged, self, master) 209 } 210 211 // BridgeVlanDel adds a new vlan filter entry 212 // Equivalent to: `bridge vlan del dev DEV vid VID [ pvid ] [ untagged ] [ self ] [ master ]` 213 func BridgeVlanDel(link Link, vid uint16, pvid, untagged, self, master bool) error { 214 return pkgHandle.BridgeVlanDel(link, vid, pvid, untagged, self, master) 215 } 216 217 // BridgeVlanDel adds a new vlan filter entry 218 // Equivalent to: `bridge vlan del dev DEV vid VID [ pvid ] [ untagged ] [ self ] [ master ]` 219 func (h *Handle) BridgeVlanDel(link Link, vid uint16, pvid, untagged, self, master bool) error { 220 return h.bridgeVlanModify(unix.RTM_DELLINK, link, vid, 0, 0, 0, pvid, untagged, self, master) 221 } 222 223 // BridgeVlanDelRange adds a new vlan filter entry 224 // Equivalent to: `bridge vlan del dev DEV vid VID-VIDEND [ pvid ] [ untagged ] [ self ] [ master ]` 225 func BridgeVlanDelRange(link Link, vid, vidEnd uint16, pvid, untagged, self, master bool) error { 226 return pkgHandle.BridgeVlanDelRange(link, vid, vidEnd, pvid, untagged, self, master) 227 } 228 229 // BridgeVlanDelRange adds a new vlan filter entry 230 // Equivalent to: `bridge vlan del dev DEV vid VID-VIDEND [ pvid ] [ untagged ] [ self ] [ master ]` 231 func (h *Handle) BridgeVlanDelRange(link Link, vid, vidEnd uint16, pvid, untagged, self, master bool) error { 232 return h.bridgeVlanModify(unix.RTM_DELLINK, link, vid, vidEnd, 0, 0, pvid, untagged, self, master) 233 } 234 235 func (h *Handle) bridgeVlanModify(cmd int, link Link, vid, vidEnd uint16, tunid, tunidEnd uint32, pvid, untagged, self, master bool) error { 236 base := link.Attrs() 237 h.ensureIndex(base) 238 req := h.newNetlinkRequest(cmd, unix.NLM_F_ACK) 239 240 msg := nl.NewIfInfomsg(unix.AF_BRIDGE) 241 msg.Index = int32(base.Index) 242 req.AddData(msg) 243 244 br := nl.NewRtAttr(unix.IFLA_AF_SPEC, nil) 245 var flags uint16 246 if self { 247 flags |= nl.BRIDGE_FLAGS_SELF 248 } 249 if master { 250 flags |= nl.BRIDGE_FLAGS_MASTER 251 } 252 if flags > 0 { 253 br.AddRtAttr(nl.IFLA_BRIDGE_FLAGS, nl.Uint16Attr(flags)) 254 } 255 256 if tunid != 0 { 257 if tunidEnd != 0 { 258 tiStart := br.AddRtAttr(nl.IFLA_BRIDGE_VLAN_TUNNEL_INFO, nil) 259 tiStart.AddRtAttr(nl.IFLA_BRIDGE_VLAN_TUNNEL_ID, nl.Uint32Attr(tunid)) 260 tiStart.AddRtAttr(nl.IFLA_BRIDGE_VLAN_TUNNEL_VID, nl.Uint16Attr(vid)) 261 tiStart.AddRtAttr(nl.IFLA_BRIDGE_VLAN_TUNNEL_FLAGS, nl.Uint16Attr(nl.BRIDGE_VLAN_INFO_RANGE_BEGIN)) 262 263 tiEnd := br.AddRtAttr(nl.IFLA_BRIDGE_VLAN_TUNNEL_INFO, nil) 264 tiEnd.AddRtAttr(nl.IFLA_BRIDGE_VLAN_TUNNEL_ID, nl.Uint32Attr(tunidEnd)) 265 tiEnd.AddRtAttr(nl.IFLA_BRIDGE_VLAN_TUNNEL_VID, nl.Uint16Attr(vidEnd)) 266 tiEnd.AddRtAttr(nl.IFLA_BRIDGE_VLAN_TUNNEL_FLAGS, nl.Uint16Attr(nl.BRIDGE_VLAN_INFO_RANGE_END)) 267 } else { 268 ti := br.AddRtAttr(nl.IFLA_BRIDGE_VLAN_TUNNEL_INFO, nil) 269 ti.AddRtAttr(nl.IFLA_BRIDGE_VLAN_TUNNEL_ID, nl.Uint32Attr(tunid)) 270 ti.AddRtAttr(nl.IFLA_BRIDGE_VLAN_TUNNEL_VID, nl.Uint16Attr(vid)) 271 ti.AddRtAttr(nl.IFLA_BRIDGE_VLAN_TUNNEL_FLAGS, nl.Uint16Attr(0)) 272 } 273 } else { 274 vlanInfo := &nl.BridgeVlanInfo{Vid: vid} 275 if pvid { 276 vlanInfo.Flags |= nl.BRIDGE_VLAN_INFO_PVID 277 } 278 if untagged { 279 vlanInfo.Flags |= nl.BRIDGE_VLAN_INFO_UNTAGGED 280 } 281 282 if vidEnd != 0 { 283 vlanEndInfo := &nl.BridgeVlanInfo{Vid: vidEnd} 284 vlanEndInfo.Flags = vlanInfo.Flags 285 286 vlanInfo.Flags |= nl.BRIDGE_VLAN_INFO_RANGE_BEGIN 287 br.AddRtAttr(nl.IFLA_BRIDGE_VLAN_INFO, vlanInfo.Serialize()) 288 289 vlanEndInfo.Flags |= nl.BRIDGE_VLAN_INFO_RANGE_END 290 br.AddRtAttr(nl.IFLA_BRIDGE_VLAN_INFO, vlanEndInfo.Serialize()) 291 } else { 292 br.AddRtAttr(nl.IFLA_BRIDGE_VLAN_INFO, vlanInfo.Serialize()) 293 } 294 } 295 296 req.AddData(br) 297 _, err := req.Execute(unix.NETLINK_ROUTE, 0) 298 return err 299 }