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  }