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