blob: 8dfded204616ea62551b865952b5f5f75630262e [file] [log] [blame]
// Copyright 2020 The Fuchsia 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 netdevice
import (
"context"
"fmt"
"syscall/zx"
"go.fuchsia.dev/fuchsia/src/connectivity/network/netstack/link"
"fidl/fuchsia/hardware/network"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/stack"
)
var _ link.Controller = (*MacAddressingClient)(nil)
var _ stack.GSOEndpoint = (*MacAddressingClient)(nil)
var _ stack.LinkEndpoint = (*MacAddressingClient)(nil)
// A fuchsia.hardware.network/Device client with an auxiliary
// fuchsia.hardware.network/MacAddressing proxy that provides the link layer
// information.
type MacAddressingClient struct {
*Client
linkAddress tcpip.LinkAddress
mac *network.MacAddressingWithCtxInterface
}
func (c *MacAddressingClient) SetPromiscuousMode(b bool) error {
var mode network.MacFilterMode
if b {
mode = network.MacFilterModePromiscuous
} else {
// NOTE: Netstack currently is not capable of handling multicast
// filters, promiscuous mode = false means receive all multicasts still.
mode = network.MacFilterModeMulticastPromiscuous
}
if status, err := c.mac.SetMode(context.Background(), mode); err != nil {
return err
} else if zx.Status(status) != zx.ErrOk {
return &zx.Error{
Status: zx.Status(status),
Text: "fuchsia.hardware.network/MacAddressing.SetMode",
}
}
return nil
}
func (c *MacAddressingClient) LinkAddress() tcpip.LinkAddress {
return c.linkAddress
}
// NewMacAddressingClient creates a new Network Device client with attached
// link-layer MAC information.
func NewMacAddressingClient(ctx context.Context, dev *network.DeviceWithCtxInterface, mac *network.MacAddressingWithCtxInterface, sessionConfigFactory SessionConfigFactory) (*MacAddressingClient, error) {
addr, err := mac.GetUnicastAddress(ctx)
if err != nil {
return nil, fmt.Errorf("failed to get mac address: %w", err)
}
linkAddress := tcpip.LinkAddress(addr.Octets[:])
client, err := NewClient(ctx, dev, sessionConfigFactory)
if err != nil {
return nil, err
}
// Set device to multicast promiscuous to match current behavior. When
// Netstack controls multicast filters this can be removed.
if status, err := mac.SetMode(ctx, network.MacFilterModeMulticastPromiscuous); err != nil {
return nil, fmt.Errorf("failed to set multicast promiscuous: %w", err)
} else if zx.Status(status) != zx.ErrOk {
return nil, &zx.Error{
Status: zx.Status(status),
Text: "fuchsia.hardware.network/MacAddressing.SetMode",
}
}
return &MacAddressingClient{
Client: client,
linkAddress: linkAddress,
mac: mac,
}, nil
}