forked from u-root/u-bmc
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This is part of u-root#56. For this to be useful the MAC address needs to be read from the interface as well. Signed-off-by: Christian Svensson <bluecmd@google.com>
- Loading branch information
Showing
2 changed files
with
157 additions
and
55 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
// Copyright 2018 the u-root Authors. All rights reserved | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
package bmc | ||
|
||
import ( | ||
"fmt" | ||
"log" | ||
"math/rand" | ||
"time" | ||
|
||
"github.com/vishvananda/netlink" | ||
"golang.org/x/sys/unix" | ||
"github.com/insomniacslk/dhcp/dhcpv6" | ||
"github.com/insomniacslk/dhcp/netboot" | ||
) | ||
|
||
const ( | ||
interfaceUpTimeout = 30 * time.Second | ||
retryDelay = 10 * time.Second | ||
retryDelaySecondsJitter = 10 | ||
) | ||
|
||
func addIp(cidr string, iface string) error { | ||
l, err := netlink.LinkByName(iface) | ||
if err != nil { | ||
return fmt.Errorf("Unable to get interface %s: %v", iface, err) | ||
} | ||
addr, err := netlink.ParseAddr(cidr) | ||
if err != nil { | ||
return fmt.Errorf("netlink.ParseAddr %v: %v", cidr, err) | ||
} | ||
h, err := netlink.NewHandle(unix.NETLINK_ROUTE) | ||
if err != nil { | ||
return fmt.Errorf("netlink.NewHandle: %v", err) | ||
} | ||
defer h.Delete() | ||
if err := h.AddrReplace(l, addr); err != nil { | ||
return fmt.Errorf("AddrReplace(%v): %v", addr, err) | ||
} | ||
return nil | ||
} | ||
|
||
func setLinkUp(iface string) error { | ||
l, err := netlink.LinkByName(iface) | ||
if err != nil { | ||
return fmt.Errorf("Unable to get interface %s: %v", iface, err) | ||
} | ||
h, err := netlink.NewHandle(unix.NETLINK_ROUTE) | ||
if err != nil { | ||
return fmt.Errorf("netlink.NewHandle: %v", err) | ||
} | ||
defer h.Delete() | ||
if err := h.LinkSetUp(l); err != nil { | ||
return fmt.Errorf("handle.LinkSetUp: %v", err) | ||
} | ||
return nil | ||
} | ||
|
||
func doRetryDelay() { | ||
delay := retryDelay + time.Duration(rand.Intn(retryDelaySecondsJitter)) * time.Second | ||
log.Printf("Waiting %v before retrying", delay) | ||
time.Sleep(delay) | ||
} | ||
|
||
func applyDhcpv6(iface string, reply *dhcpv6.DHCPv6Message) error { | ||
log.Printf("reply: %v", reply) | ||
return nil | ||
} | ||
|
||
func autoconfigInterface(iface string) { | ||
for { | ||
_, err := netboot.IfUp(iface, interfaceUpTimeout) | ||
if err != nil { | ||
log.Printf("Timeout waiting for link up on %s", iface) | ||
continue | ||
} | ||
|
||
client := dhcpv6.NewClient() | ||
conv, err := client.Exchange(iface, nil) | ||
if err != nil { | ||
log.Printf("DHCPv6 exchange failed for %s: %v", iface, err) | ||
doRetryDelay() | ||
continue | ||
} | ||
|
||
var reply dhcpv6.DHCPv6 | ||
for _, m := range conv { | ||
if m.Type() == dhcpv6.MessageTypeReply { | ||
reply = m | ||
break | ||
} | ||
} | ||
if reply == nil { | ||
log.Printf("No DHCPv6 reply found conversation for %s", iface) | ||
doRetryDelay() | ||
continue | ||
} | ||
if err := applyDhcpv6(iface, reply.(*dhcpv6.DHCPv6Message)); err != nil { | ||
log.Printf("Failed to apply DHCPv6 configuration for %s: %v", iface, err) | ||
doRetryDelay() | ||
continue | ||
} | ||
} | ||
} | ||
|
||
func ConfigureInterfaces() error { | ||
unix.Sethostname([]byte("ubmc")) | ||
|
||
// Fun story: if you don't have both IPv4 and IPv6 loopback configured | ||
// golang binaries will not bind to :: but to 0.0.0.0 instead. | ||
// Isn't that surprising? | ||
if err := addIp("127.0.0.1/8", "lo"); err != nil { | ||
return err | ||
} | ||
if err := addIp("::1/32", "lo"); err != nil { | ||
return err | ||
} | ||
if err := setLinkUp("lo"); err != nil { | ||
return err | ||
} | ||
|
||
// TODO(bluecmd): Read MAC address from NC-SI | ||
|
||
// TODO(bluecmd): Remove when DHCPv6 works | ||
addIp("10.0.10.20/24", "eth0") | ||
|
||
go autoconfigInterface("eth0") | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters