github.com/metacubex/gvisor@v0.0.0-20240320004321-933faba989ec/pkg/sentry/fsimpl/sys/net.go (about)

     1  // Copyright 2022 The gVisor Authors.
     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  
    15  package sys
    16  
    17  import (
    18  	"bytes"
    19  	"fmt"
    20  	"time"
    21  
    22  	"github.com/metacubex/gvisor/pkg/abi/linux"
    23  	"github.com/metacubex/gvisor/pkg/context"
    24  	"github.com/metacubex/gvisor/pkg/sentry/fsimpl/kernfs"
    25  	"github.com/metacubex/gvisor/pkg/sentry/inet"
    26  	"github.com/metacubex/gvisor/pkg/sentry/kernel/auth"
    27  	"github.com/metacubex/gvisor/pkg/sentry/vfs"
    28  	"github.com/metacubex/gvisor/pkg/usermem"
    29  )
    30  
    31  // newNetDir returns a directory containing a subdirectory for each network
    32  // interface.
    33  func (fs *filesystem) newNetDir(ctx context.Context, creds *auth.Credentials, mode linux.FileMode) map[string]kernfs.Inode {
    34  	// Get list of interfaces.
    35  	stk := inet.StackFromContext(ctx)
    36  	if stk == nil {
    37  		return map[string]kernfs.Inode{}
    38  	}
    39  
    40  	subDirs := make(map[string]kernfs.Inode)
    41  	for idx, iface := range stk.Interfaces() {
    42  		subDirs[iface.Name] = fs.newIfaceDir(ctx, creds, mode, idx, stk)
    43  	}
    44  	return subDirs
    45  }
    46  
    47  // newIfaceDir returns a directory containing per-interface files.
    48  func (fs *filesystem) newIfaceDir(ctx context.Context, creds *auth.Credentials, mode linux.FileMode, idx int32, stk inet.Stack) kernfs.Inode {
    49  	files := map[string]kernfs.Inode{
    50  		"gro_flush_timeout": fs.newGROTimeoutFile(ctx, creds, mode, idx, stk),
    51  	}
    52  	return fs.newDir(ctx, creds, mode, files)
    53  }
    54  
    55  // groTimeoutFile enables the reading and writing of the GRO timeout.
    56  //
    57  // +stateify savable
    58  type groTimeoutFile struct {
    59  	implStatFS
    60  	kernfs.DynamicBytesFile
    61  
    62  	idx int32
    63  	stk inet.Stack
    64  }
    65  
    66  // newGROTimeoutFile returns a file that can be used to read and set the GRO
    67  // timeout.
    68  func (fs *filesystem) newGROTimeoutFile(ctx context.Context, creds *auth.Credentials, mode linux.FileMode, idx int32, stk inet.Stack) kernfs.Inode {
    69  	file := groTimeoutFile{idx: idx, stk: stk}
    70  	file.DynamicBytesFile.Init(ctx, creds, linux.UNNAMED_MAJOR, fs.devMinor, fs.NextIno(), &file, mode)
    71  	return &file
    72  }
    73  
    74  // Generate implements vfs.DynamicBytesSource.Generate.
    75  func (gf *groTimeoutFile) Generate(ctx context.Context, buf *bytes.Buffer) error {
    76  	timeout, err := gf.stk.GROTimeout(gf.idx)
    77  	if err != nil {
    78  		return err
    79  	}
    80  	fmt.Fprintf(buf, "%d\n", timeout.Nanoseconds())
    81  	return nil
    82  }
    83  
    84  // Write implements vfs.WritableDynamicBytesSource.Write.
    85  func (gf *groTimeoutFile) Write(ctx context.Context, _ *vfs.FileDescription, src usermem.IOSequence, offset int64) (int64, error) {
    86  	val := []int32{0}
    87  	nRead, err := usermem.CopyInt32StringsInVec(ctx, src.IO, src.Addrs, val, src.Opts)
    88  	if err != nil {
    89  		return 0, err
    90  	}
    91  	gf.stk.SetGROTimeout(gf.idx, time.Duration(val[0])*time.Nanosecond)
    92  	return nRead, nil
    93  }