interface.go 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. // Copyright 2015 CoreOS, Inc.
  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. package network
  15. import (
  16. "fmt"
  17. "net"
  18. "sort"
  19. "strconv"
  20. "strings"
  21. )
  22. type InterfaceGenerator interface {
  23. Name() string
  24. Filename() string
  25. Netdev() string
  26. Link() string
  27. Network() string
  28. Type() string
  29. ModprobeParams() string
  30. }
  31. type networkInterface interface {
  32. InterfaceGenerator
  33. Children() []networkInterface
  34. setConfigDepth(int)
  35. }
  36. type logicalInterface struct {
  37. name string
  38. hwaddr net.HardwareAddr
  39. config configMethod
  40. children []networkInterface
  41. configDepth int
  42. }
  43. func (i *logicalInterface) Name() string {
  44. return i.name
  45. }
  46. func (i *logicalInterface) Network() string {
  47. config := fmt.Sprintln("[Match]")
  48. if i.name != "" {
  49. config += fmt.Sprintf("Name=%s\n", i.name)
  50. }
  51. if i.hwaddr != nil {
  52. config += fmt.Sprintf("MACAddress=%s\n", i.hwaddr)
  53. }
  54. config += "\n[Network]\n"
  55. for _, child := range i.children {
  56. switch iface := child.(type) {
  57. case *vlanInterface:
  58. config += fmt.Sprintf("VLAN=%s\n", iface.name)
  59. case *bondInterface:
  60. config += fmt.Sprintf("Bond=%s\n", iface.name)
  61. }
  62. }
  63. switch conf := i.config.(type) {
  64. case configMethodStatic:
  65. if len(conf.domains) > 0 {
  66. config += fmt.Sprintf("Domains=%s\n", strings.Join(conf.domains, " "))
  67. }
  68. for _, nameserver := range conf.nameservers {
  69. config += fmt.Sprintf("DNS=%s\n", nameserver)
  70. }
  71. for _, addr := range conf.addresses {
  72. config += fmt.Sprintf("\n[Address]\nAddress=%s\n", addr.String())
  73. }
  74. for _, route := range conf.routes {
  75. config += fmt.Sprintf("\n[Route]\nDestination=%s\nGateway=%s\n", route.destination.String(), route.gateway)
  76. }
  77. case configMethodDHCP:
  78. config += "DHCP=true\n"
  79. }
  80. return config
  81. }
  82. func (i *logicalInterface) Link() string {
  83. return ""
  84. }
  85. func (i *logicalInterface) Netdev() string {
  86. return ""
  87. }
  88. func (i *logicalInterface) Filename() string {
  89. name := i.name
  90. if name == "" {
  91. name = i.hwaddr.String()
  92. }
  93. return fmt.Sprintf("%02x-%s", i.configDepth, name)
  94. }
  95. func (i *logicalInterface) Children() []networkInterface {
  96. return i.children
  97. }
  98. func (i *logicalInterface) ModprobeParams() string {
  99. return ""
  100. }
  101. func (i *logicalInterface) setConfigDepth(depth int) {
  102. i.configDepth = depth
  103. }
  104. type physicalInterface struct {
  105. logicalInterface
  106. }
  107. func (p *physicalInterface) Type() string {
  108. return "physical"
  109. }
  110. type bondInterface struct {
  111. logicalInterface
  112. slaves []string
  113. options map[string]string
  114. }
  115. func (b *bondInterface) Netdev() string {
  116. config := fmt.Sprintf("[NetDev]\nKind=bond\nName=%s\n", b.name)
  117. if b.hwaddr != nil {
  118. config += fmt.Sprintf("MACAddress=%s\n", b.hwaddr.String())
  119. }
  120. config += fmt.Sprintf("\n[Bond]\n")
  121. for _, name := range sortedKeys(b.options) {
  122. config += fmt.Sprintf("%s=%s\n", name, b.options[name])
  123. }
  124. return config
  125. }
  126. func (b *bondInterface) Type() string {
  127. return "bond"
  128. }
  129. func (b *bondInterface) ModprobeParams() string {
  130. params := ""
  131. for _, name := range sortedKeys(b.options) {
  132. params += fmt.Sprintf("%s=%s ", name, b.options[name])
  133. }
  134. params = strings.TrimSuffix(params, " ")
  135. return params
  136. }
  137. type vlanInterface struct {
  138. logicalInterface
  139. id int
  140. rawDevice string
  141. }
  142. func (v *vlanInterface) Netdev() string {
  143. config := fmt.Sprintf("[NetDev]\nKind=vlan\nName=%s\n", v.name)
  144. switch c := v.config.(type) {
  145. case configMethodStatic:
  146. if c.hwaddress != nil {
  147. config += fmt.Sprintf("MACAddress=%s\n", c.hwaddress)
  148. }
  149. case configMethodDHCP:
  150. if c.hwaddress != nil {
  151. config += fmt.Sprintf("MACAddress=%s\n", c.hwaddress)
  152. }
  153. }
  154. config += fmt.Sprintf("\n[VLAN]\nId=%d\n", v.id)
  155. return config
  156. }
  157. func (v *vlanInterface) Type() string {
  158. return "vlan"
  159. }
  160. func buildInterfaces(stanzas []*stanzaInterface) []InterfaceGenerator {
  161. interfaceMap := createInterfaces(stanzas)
  162. linkAncestors(interfaceMap)
  163. markConfigDepths(interfaceMap)
  164. interfaces := make([]InterfaceGenerator, 0, len(interfaceMap))
  165. for _, name := range sortedInterfaces(interfaceMap) {
  166. interfaces = append(interfaces, interfaceMap[name])
  167. }
  168. return interfaces
  169. }
  170. func createInterfaces(stanzas []*stanzaInterface) map[string]networkInterface {
  171. interfaceMap := make(map[string]networkInterface)
  172. for _, iface := range stanzas {
  173. switch iface.kind {
  174. case interfaceBond:
  175. bondOptions := make(map[string]string)
  176. for _, k := range []string{"mode", "miimon", "lacp-rate"} {
  177. if v, ok := iface.options["bond-"+k]; ok && len(v) > 0 {
  178. bondOptions[k] = v[0]
  179. }
  180. }
  181. interfaceMap[iface.name] = &bondInterface{
  182. logicalInterface{
  183. name: iface.name,
  184. config: iface.configMethod,
  185. children: []networkInterface{},
  186. },
  187. iface.options["bond-slaves"],
  188. bondOptions,
  189. }
  190. for _, slave := range iface.options["bond-slaves"] {
  191. if _, ok := interfaceMap[slave]; !ok {
  192. interfaceMap[slave] = &physicalInterface{
  193. logicalInterface{
  194. name: slave,
  195. config: configMethodManual{},
  196. children: []networkInterface{},
  197. },
  198. }
  199. }
  200. }
  201. case interfacePhysical:
  202. if _, ok := iface.configMethod.(configMethodLoopback); ok {
  203. continue
  204. }
  205. interfaceMap[iface.name] = &physicalInterface{
  206. logicalInterface{
  207. name: iface.name,
  208. config: iface.configMethod,
  209. children: []networkInterface{},
  210. },
  211. }
  212. case interfaceVLAN:
  213. var rawDevice string
  214. id, _ := strconv.Atoi(iface.options["id"][0])
  215. if device := iface.options["raw_device"]; len(device) == 1 {
  216. rawDevice = device[0]
  217. if _, ok := interfaceMap[rawDevice]; !ok {
  218. interfaceMap[rawDevice] = &physicalInterface{
  219. logicalInterface{
  220. name: rawDevice,
  221. config: configMethodManual{},
  222. children: []networkInterface{},
  223. },
  224. }
  225. }
  226. }
  227. interfaceMap[iface.name] = &vlanInterface{
  228. logicalInterface{
  229. name: iface.name,
  230. config: iface.configMethod,
  231. children: []networkInterface{},
  232. },
  233. id,
  234. rawDevice,
  235. }
  236. }
  237. }
  238. return interfaceMap
  239. }
  240. func linkAncestors(interfaceMap map[string]networkInterface) {
  241. for _, name := range sortedInterfaces(interfaceMap) {
  242. iface := interfaceMap[name]
  243. switch i := iface.(type) {
  244. case *vlanInterface:
  245. if parent, ok := interfaceMap[i.rawDevice]; ok {
  246. switch p := parent.(type) {
  247. case *physicalInterface:
  248. p.children = append(p.children, iface)
  249. case *bondInterface:
  250. p.children = append(p.children, iface)
  251. }
  252. }
  253. case *bondInterface:
  254. for _, slave := range i.slaves {
  255. if parent, ok := interfaceMap[slave]; ok {
  256. switch p := parent.(type) {
  257. case *physicalInterface:
  258. p.children = append(p.children, iface)
  259. case *bondInterface:
  260. p.children = append(p.children, iface)
  261. }
  262. }
  263. }
  264. }
  265. }
  266. }
  267. func markConfigDepths(interfaceMap map[string]networkInterface) {
  268. rootInterfaceMap := make(map[string]networkInterface)
  269. for k, v := range interfaceMap {
  270. rootInterfaceMap[k] = v
  271. }
  272. for _, iface := range interfaceMap {
  273. for _, child := range iface.Children() {
  274. delete(rootInterfaceMap, child.Name())
  275. }
  276. }
  277. for _, iface := range rootInterfaceMap {
  278. setDepth(iface)
  279. }
  280. }
  281. func setDepth(iface networkInterface) int {
  282. maxDepth := 0
  283. for _, child := range iface.Children() {
  284. if depth := setDepth(child); depth > maxDepth {
  285. maxDepth = depth
  286. }
  287. }
  288. iface.setConfigDepth(maxDepth)
  289. return (maxDepth + 1)
  290. }
  291. func sortedKeys(m map[string]string) (keys []string) {
  292. for key := range m {
  293. keys = append(keys, key)
  294. }
  295. sort.Strings(keys)
  296. return
  297. }
  298. func sortedInterfaces(m map[string]networkInterface) (keys []string) {
  299. for key := range m {
  300. keys = append(keys, key)
  301. }
  302. sort.Strings(keys)
  303. return
  304. }