| // 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 | |
| } |