go.ligato.io/vpp-agent/v3@v3.5.0/proto/ligato/linux/interfaces/models.go (about)

     1  // Copyright (c) 2017 Cisco and/or its affiliates.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at:
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package linux_interfaces
    16  
    17  import (
    18  	"strings"
    19  
    20  	"go.ligato.io/vpp-agent/v3/pkg/models"
    21  	"go.ligato.io/vpp-agent/v3/proto/ligato/netalloc"
    22  )
    23  
    24  // ModuleName is the module name used for models.
    25  const ModuleName = "linux.interfaces"
    26  
    27  var (
    28  	ModelInterface = models.Register(&Interface{}, models.Spec{
    29  		Module:  ModuleName,
    30  		Version: "v2",
    31  		Type:    "interface",
    32  	})
    33  )
    34  
    35  // InterfaceKey returns the key used in ETCD to store configuration of a particular Linux interface.
    36  func InterfaceKey(name string) string {
    37  	return models.Key(&Interface{
    38  		Name: name,
    39  	})
    40  }
    41  
    42  const (
    43  	/* Interface host-name (default ns only, notifications) */
    44  
    45  	// InterfaceHostNameKeyPrefix is the common prefix of all keys representing
    46  	// existing Linux interfaces in the default namespace (referenced by host names).
    47  	InterfaceHostNameKeyPrefix = "linux/interface/host-name/"
    48  
    49  	interfaceHostNameWithAddrKeyTmpl = InterfaceHostNameKeyPrefix + "{host-name}/address/{address}"
    50  	interfaceHostNameWithVrfKeyTmpl  = InterfaceHostNameKeyPrefix + "{host-name}/vrf-host-name/{vrf-host-name}"
    51  
    52  	/* Interface State (derived) */
    53  
    54  	// InterfaceStateKeyPrefix is used as a common prefix for keys derived from
    55  	// interfaces to represent the interface admin state (up/down).
    56  	InterfaceStateKeyPrefix = "linux/interface/state/"
    57  
    58  	// interfaceStateKeyTemplate is a template for (derived) key representing interface
    59  	// admin state (up/down).
    60  	interfaceStateKeyTemplate = InterfaceStateKeyPrefix + "{ifName}/{ifState}"
    61  
    62  	// interface admin state as printed in derived keys.
    63  	interfaceUpState   = "UP"
    64  	interfaceDownState = "DOWN"
    65  
    66  	/* Interface Address (derived) */
    67  
    68  	// interfaceAddressKeyPrefix is used as a common prefix for keys derived from
    69  	// interfaces to represent assigned IP addresses.
    70  	interfaceAddrKeyPrefix = "linux/interface/{iface}/address/"
    71  
    72  	// interfaceAddrKeyTmpl is a template for (derived) key representing IP address
    73  	// (incl. mask) assigned to a Linux interface (referenced by the logical name).
    74  	interfaceAddrKeyTmpl = interfaceAddrKeyPrefix + "{address-source}/{address}"
    75  
    76  	/* Interface VRF (derived) */
    77  
    78  	// interfaceVrfKeyTmpl is a template for (derived) key representing assignment
    79  	// of a Linux interface into a VRF.
    80  	interfaceVrfKeyTmpl = "linux/interface/{iface}/vrf/{vrf}"
    81  )
    82  
    83  const (
    84  	// InvalidKeyPart is used in key for parts which are invalid
    85  	InvalidKeyPart = "<invalid>"
    86  )
    87  
    88  /* Interface host-name (default ns only, notifications) */
    89  
    90  // InterfaceHostNameKey returns key representing Linux interface host name.
    91  func InterfaceHostNameKey(hostName string) string {
    92  	return InterfaceHostNameKeyPrefix + hostName
    93  }
    94  
    95  // InterfaceHostNameWithAddrKey returns key representing assignment of an IP address
    96  // to a Linux interface referenced by its host name.
    97  // If address is empty, the function returns key prefix matching any IP address.
    98  func InterfaceHostNameWithAddrKey(hostName, address string) string {
    99  	if hostName == "" {
   100  		hostName = InvalidKeyPart
   101  	}
   102  	tmpl := interfaceHostNameWithAddrKeyTmpl
   103  	key := strings.Replace(tmpl, "{host-name}", hostName, 1)
   104  	key = strings.Replace(key, "{address}", address, 1)
   105  	return key
   106  }
   107  
   108  // InterfaceHostNameWithVrfKey returns key representing association between Linux
   109  // interface and Linux VRF, both referenced by host names.
   110  // If vrf is empty, the function returns key prefix matching any VRF.
   111  func InterfaceHostNameWithVrfKey(hostName, vrf string) string {
   112  	if hostName == "" {
   113  		hostName = InvalidKeyPart
   114  	}
   115  	tmpl := interfaceHostNameWithVrfKeyTmpl
   116  	key := strings.Replace(tmpl, "{host-name}", hostName, 1)
   117  	key = strings.Replace(key, "{vrf-host-name}", vrf, 1)
   118  	return key
   119  }
   120  
   121  /* Interface State (derived) */
   122  
   123  // InterfaceStateKey returns key representing admin state of a Linux interface.
   124  func InterfaceStateKey(ifName string, ifIsUp bool) string {
   125  	ifState := interfaceDownState
   126  	if ifIsUp {
   127  		ifState = interfaceUpState
   128  	}
   129  	key := strings.Replace(interfaceStateKeyTemplate, "{ifName}", ifName, 1)
   130  	key = strings.Replace(key, "{ifState}", ifState, 1)
   131  	return key
   132  }
   133  
   134  // ParseInterfaceStateKey parses interface name and state from key derived
   135  // from interface by InterfaceStateKey().
   136  func ParseInterfaceStateKey(key string) (ifName string, ifIsUp bool, isStateKey bool) {
   137  	if strings.HasPrefix(key, InterfaceStateKeyPrefix) {
   138  		keySuffix := strings.TrimPrefix(key, InterfaceStateKeyPrefix)
   139  		keyComps := strings.Split(keySuffix, "/")
   140  		if len(keyComps) != 2 {
   141  			return "", false, false
   142  		}
   143  		ifName = keyComps[0]
   144  		isStateKey = true
   145  		if keyComps[1] == interfaceUpState {
   146  			ifIsUp = true
   147  		}
   148  		return
   149  	}
   150  	return "", false, false
   151  }
   152  
   153  /* Interface Address (derived) */
   154  
   155  // InterfaceAddressPrefix returns longest-common prefix of keys representing
   156  // assigned IP addresses to a specific Linux interface.
   157  func InterfaceAddressPrefix(iface string) string {
   158  	if iface == "" {
   159  		iface = InvalidKeyPart
   160  	}
   161  	return strings.Replace(interfaceAddrKeyPrefix, "{iface}", iface, 1)
   162  }
   163  
   164  // InterfaceAddressKey returns key representing IP address assigned to Linux interface.
   165  // With undefined vrf the returned key can be also used as a key prefix, matching derived
   166  // interface address key regardless of the VRF to which it belongs.
   167  func InterfaceAddressKey(iface, address string, source netalloc.IPAddressSource) string {
   168  	if iface == "" {
   169  		iface = InvalidKeyPart
   170  	}
   171  
   172  	src := source.String()
   173  	if src == "" {
   174  		src = InvalidKeyPart
   175  	}
   176  	if strings.HasPrefix(address, netalloc.AllocRefPrefix) {
   177  		src = netalloc.IPAddressSource_ALLOC_REF.String()
   178  	}
   179  	src = strings.ToLower(src)
   180  
   181  	// construct key without validating the IP address
   182  	tmpl := interfaceAddrKeyTmpl
   183  	key := strings.Replace(tmpl, "{iface}", iface, 1)
   184  	key = strings.Replace(key, "{address-source}", src, 1)
   185  	key = strings.Replace(key, "{address}", address, 1)
   186  	return key
   187  }
   188  
   189  // ParseInterfaceAddressKey parses interface address from key derived
   190  // from interface by InterfaceAddressKey().
   191  func ParseInterfaceAddressKey(key string) (iface, address string, source netalloc.IPAddressSource,
   192  	invalidKey, isAddrKey bool) {
   193  	parts := strings.Split(key, "/")
   194  	if len(parts) < 4 || parts[0] != "linux" || parts[1] != "interface" {
   195  		return
   196  	}
   197  	if parts[2] == "state" || parts[2] == "host-name" {
   198  		return
   199  	}
   200  
   201  	addrIdx := -1
   202  	for idx, part := range parts {
   203  		switch part {
   204  		case "vrf":
   205  			// avoid collision with InterfaceVrfKey
   206  			return
   207  		case "address":
   208  			addrIdx = idx
   209  		}
   210  	}
   211  	if addrIdx == -1 {
   212  		return
   213  	}
   214  	isAddrKey = true
   215  
   216  	// parse interface name
   217  	iface = strings.Join(parts[2:addrIdx], "/")
   218  	if iface == "" {
   219  		iface = InvalidKeyPart
   220  		invalidKey = true
   221  	}
   222  
   223  	// parse address source
   224  	src := strings.ToUpper(parts[addrIdx+1])
   225  	srcInt, validSrc := netalloc.IPAddressSource_value[src]
   226  	if !validSrc {
   227  		invalidKey = true
   228  		return
   229  	}
   230  	source = netalloc.IPAddressSource(srcInt)
   231  
   232  	// return address as is (not parsed - this is done by the netalloc plugin)
   233  	if addrIdx == len(parts)-1 {
   234  		invalidKey = true
   235  		return
   236  	}
   237  	address = strings.Join(parts[addrIdx+2:], "/")
   238  	if address == "" {
   239  		invalidKey = true
   240  	}
   241  	return
   242  }
   243  
   244  // InterfaceVrfKey returns key representing assignment of a Linux interface into a VRF.
   245  func InterfaceVrfKey(iface string, vrf string) string {
   246  	if iface == "" {
   247  		iface = InvalidKeyPart
   248  	}
   249  	if vrf == "" {
   250  		vrf = InvalidKeyPart
   251  	}
   252  
   253  	tmpl := interfaceVrfKeyTmpl
   254  	key := strings.Replace(tmpl, "{iface}", iface, 1)
   255  	key = strings.Replace(key, "{vrf}", vrf, 1)
   256  	return key
   257  }
   258  
   259  // ParseInterfaceVrfKey parses interface VRF from key derived
   260  // from interface by InterfaceVrfKey().
   261  func ParseInterfaceVrfKey(key string) (iface string, vrf string, invalidKey, isVrfKey bool) {
   262  	parts := strings.Split(key, "/")
   263  	if len(parts) < 4 || parts[0] != "linux" || parts[1] != "interface" {
   264  		return
   265  	}
   266  	if parts[2] == "state" || parts[2] == "host-name" {
   267  		return
   268  	}
   269  
   270  	vrfIdx := -1
   271  	for idx, part := range parts {
   272  		switch part {
   273  		case "address":
   274  			// avoid collision with InterfaceAddressKey
   275  			return
   276  		case "vrf":
   277  			vrfIdx = idx
   278  		}
   279  	}
   280  	if vrfIdx == -1 {
   281  		return
   282  	}
   283  	isVrfKey = true
   284  
   285  	// parse interface name
   286  	iface = strings.Join(parts[2:vrfIdx], "/")
   287  	if iface == "" {
   288  		iface = InvalidKeyPart
   289  		invalidKey = true
   290  	}
   291  
   292  	// parse VRF
   293  	if vrfIdx == len(parts)-1 {
   294  		invalidKey = true
   295  		vrf = InvalidKeyPart
   296  		return
   297  	}
   298  	vrf = parts[vrfIdx+1]
   299  	return
   300  }