resource

package
v1.1.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 24, 2026 License: MIT Imports: 2 Imported by: 0

Documentation

Overview

Package resource は Resource Guard(設計文書 7a.5、7a.10 節)。wgft 自身が保持するフローの プロセス全体の予算と、その予算から導くルールごとの隔離とメモリのソフト上限を持つ。 エージェントの中継(relay)と vpsd のプロキシモードの中継(proxyrelay)が共有する。 プロセス全体の数とルールごとの数は、Pool が 1 つの排他の中で数える。

利用者が設定する通信方針(送信元ごとの同時フロー数の上限)は Admission Policy に属し、 internal/policy の AdmissionLimits が持つ(設計文書 7a.10 節の型の分割)。

Index

Constants

View Source
const (
	UDPTotal = 8192
	TCPTotal = 2048

	// プロセス全体の上限に設定できる範囲
	TotalMin = 16
	TotalMax = 65535
)

仕様 7 節の値。プロセス全体の上限(WGFT_MAX_UDP_FLOWS、WGFT_MAX_TCP_FLOWS)が設定項目で、 ここはその既定値。ルール 1 本の上限と隔離予約は設定項目ではなく、この上限から Pool が導く。

Variables

This section is empty.

Functions

This section is empty.

Types

type Limits

type Limits struct {
	UDPTotal int
	TCPTotal int
}

Limits はプロセス全体のフロー予算(設定値)。どの項目もゼロ値なら既定値を使う(WithDefaults)。 ゼロ値を「上限なし」にすると、設定層を通らずに組み立てた Limits で守りが黙って外れるためである。

func (Limits) MemoryLimit

func (l Limits) MemoryLimit() int64

MemoryLimit は、この上限で動くプロセスに設定するメモリのソフト上限(バイト)。 係数はラボの実測からの定数で、ホストのメモリの量は見ない(仕様 7 節)。

func (Limits) WithDefaults

func (l Limits) WithDefaults() Limits

WithDefaults はゼロ値の項目を既定値で埋める。

type Listener

type Listener struct {
	// contains filtered or unexported fields
}

Listener は Pool に登録した待ち受け 1 つ。フローの枠はこの型を通して取る。 どの項目も Pool の排他が守るので、複数の goroutine から呼べる。

func (*Listener) Accept

func (l *Listener) Accept()

Accept は StopAccepting でやめた受け付けを再開する(宣言に戻った UDP の待ち受け)。

func (*Listener) Acquire

func (l *Listener) Acquire() (Refusal, bool)

Acquire はフロー 1 つ分の枠を取る。取れたら真を返し、呼び出し側はフローの終わりに Release を 1 回呼ぶ。取れなければ理由を返し、何も数えない。拒否は理由ごとの数に 1 を足す。

判定は数の帳簿だけを見るので、受け付けていない handle(Retiring と、bind の済んでいない PendingListener)でも枠は取れる。取った枠はプロセス全体の数 u に入り、ルールごとの数 u_r には 入らず、そのルールを A にも入れない。中継は、待ち受けを Retiring にするときにソケットを閉じ、 bind が済んで Accept を呼んでから中継を始めるので、この状態で Acquire を呼ぶのは、閉じる直前に accept してしまったフローだけである。

func (*Listener) Close

func (l *Listener) Close()

Close は待ち受けを Pool から外す。まだ返していないフローは、Release を呼ぶまでプロセス全体の数に 残る(閉じた待ち受けのフローは、中継が閉じ終えるまで資源を使っているため)。

func (*Listener) Flows

func (l *Listener) Flows() int

Flows はこの待ち受けが保持しているフローの数。

func (*Listener) Release

func (l *Listener) Release()

Release は Acquire で取った枠を返す。Acquire が真を返した回数より多く呼ばれたときは何もしない。 数を負にすると、以後の判定が予算を過大に空いていると見て守りが外れるためである。

func (*Listener) SetRule

func (l *Listener) SetRule(ruleID string)

SetRule は所属ルールを付け替える(分割と統合の relabel)。既存のフローは移動先のルールで数える。

func (*Listener) StopAccepting

func (l *Listener) StopAccepting()

StopAccepting は、この待ち受けを新しいフローを受け付けない状態にする(設計文書 7a.3 節の Retiring)。残っているフローはプロセス全体の数 u に入り続けるが、ルールごとの数 u_r からは 外れ、そのルールは待ち受けが他に無ければ A から外れる。ルール単位の fail-closed はそのルールの 待ち受けをすべて Retiring にするので、そのルールは新しいフローを受け付けているルールではなくなる。

type Pool

type Pool struct {
	// contains filtered or unexported fields
}

Pool は 1 つのプロトコルのフロー予算(設計文書 7a.5、7a.10 節の Resource Guard)。プロセス全体の 予算 T を共有プールとし、受け付けているルールごとの隔離予約で 1 つのルールへのフラッドが他の ルールの新しいフローを止めることを防ぐ。判定は 1 つの排他の中で行い、ルールごと、理由ごとの 拒否の数を、この Pool を作ってからの累計として持つ。SQLite には保存しない。累計の起点は 呼び出し側の作り方で決まる。vpsd はプロセスの起動時に 1 つ作るのでプロセスが起動してからの 累計になり、エージェントはトンネルを立て直すたびに中継ごと作り直すので、そのたびに 0 に戻る (設計文書 10.2c 節の relay.refusals)。

フローは待ち受け(Listener)に付けて数え、待ち受けから所属ルールへの対応は Pool が持つ。 ルールのフロー数は、そのルールの受け付けている待ち受けのフロー数の合計である。分割と統合で 待ち受けの所属ルールが変わると、その待ち受けの既存のフローは移動先のルールで数える (仕様 7 節の規則のまま)。

記号は設計文書 7a.10 節に合わせる。T は予算、C はルールが 2 本以上あるときのルール 1 本の上限 (ceil(T/2))、A は受け付けているルールの集合、N は A の大きさ、q は N が 2 以上のときの floor((T - C) / (N - 1))、u はプロセス全体のフロー数、u_r はルール r のフロー数である。 ルール r の新しいフローは、u < T であり、N が 2 以上なら u_r < C であり、かつ u_r < q または T - u - Σ max(0, q - u_s) >= 1(和は A のうち r 以外)のときに通す。

判定を 1 回あたり一定の手間で済ませるため、u_r と Σ max(0, q - u_s) は足し引きで保つ。 q は N が変わったときだけ変わるので、待ち受けの登録、閉鎖、受け付けの開始と停止、所属ルールの 付け替えのときに作り直す(設計文書 7a.10 節が A と q を Commit で更新すると定めているとおり、 この 5 つの操作はどれも収束の Commit から呼ばれる)。

func NewPool

func NewPool(total int) *Pool

NewPool は予算 total のプールを作る。ルール 1 本の上限と隔離予約は total から導く。

func (*Pool) InUse

func (p *Pool) InUse() int

InUse は今保持しているフローの数 u。受け付けをやめた待ち受けと、閉じた待ち受けの残りのフローも含む。

func (*Pool) Listener

func (p *Pool) Listener(ruleID string) *Listener

Listener は待ち受け 1 つ分の枠を Pool に登録する。呼び出し側は待ち受けを閉じるときに Close を呼ぶ。 この handle は登録した時点で新しいフローを受け付けている状態になり、そのルールは A に入る。 bind をまだ試みていない、または bind の成否に関わらず handle を保ちたい呼び出し側は、代わりに PendingListener を使う。

func (*Pool) PendingListener

func (p *Pool) PendingListener(ruleID string) *Listener

PendingListener は、まだ新しいフローを受け付けられない待ち受けの枠を登録する。そのルールは Accept を呼ぶまで A に入らない。A は開けた待ち受けを持つルールの集合なので(設計文書 7a.10 節)、bind の 最中の待ち受けと bind に失敗した待ち受けが、その間だけ N を増やして他のルールの予約を減らすことを 防ぐ。

2026-09-20 より前はこの handle をソケットの bind の前に作る設計だったが、今の本番の呼び出し側は どちらも bind を試みた後に handle を作る。relay.Manager.newListener は bind の成否に関わらず handle を作り(30 秒ごとの Retry が失敗した待ち受けを扱えるようにするため)、成功したときだけ Accept を呼ぶ。proxyrelay は逆に、bind に失敗したポートには handle を一切作らず(Prepare の時点で 開けたポートだけを Commit で登録し、Listener を直接使う)、Pending の状態を経ない。どちらの形でも bind が終わる前や失敗した待ち受けのルールを N に数えないことに変わりは無く、Pending の状態は この防止のために残す。

func (*Pool) Refusals

func (p *Pool) Refusals() map[string]map[Reason]uint64

Refusals はルール ID から理由ごとの拒否の数への表を複製して返す。

func (*Pool) Reserve

func (p *Pool) Reserve() int

Reserve はルール 1 本あたりの隔離予約 q。

func (*Pool) RuleCap

func (p *Pool) RuleCap() int

RuleCap はルールが 2 本以上あるときのルール 1 本の上限 C。ルールが 1 本のときは効かない。

func (*Pool) RuleFlows

func (p *Pool) RuleFlows(ruleID string) int

RuleFlows はそのルールのフロー数 u_r(受け付けている待ち受けの合計)。

func (*Pool) Rules

func (p *Pool) Rules() int

Rules は今受け付けているルールの数 N。

func (*Pool) Total

func (p *Pool) Total() int

Total は予算 T。

type Reason

type Reason string

Reason は Pool が新しいフローを拒んだ理由(設計文書 7a.10 節の「拒否の報告」)。 Admission Policy の drop の種類とは別で、SQLite にも drop カウンタにも混ぜない。

const (
	// ReasonBudget はプロセス全体の予算が埋まっていること(u < T を満たさない)。
	ReasonBudget Reason = "budget"
	// ReasonRuleCap はルール 1 本の上限 C に達していること(ルールが 2 本以上あるときだけ効く)。
	ReasonRuleCap Reason = "rule_cap"
	// ReasonReserve は、自分の隔離予約を超えていて、残りの空きが他のルールの予約で埋まっていること。
	ReasonReserve Reason = "reserve"
)

type Refusal

type Refusal struct {
	Reason     Reason
	RuleID     string
	InUse      int // 判定したときのプロセス全体のフロー数 u
	Total      int // プロセス全体の予算 T
	RuleFlows  int // 判定したときのそのルールのフロー数 u_r。予算で拒んだときは数えないので 0
	RuleCap    int // ルールが 2 本以上あるときのルール 1 本の上限 C
	Reserve    int // ルール 1 本あたりの隔離予約 q
	OtherRules int // 予約を持つ他のルールの数(新しいフローを受け付けているルールのうち自分以外)
}

Refusal は拒んだ 1 回の判定の内訳。中継はこれをログの文言にする(設計文書 7a.10 節)。

func (Refusal) String

func (r Refusal) String() string

String は理由を説明する 1 文。中継は待ち受けの名前と処置を前後に付けてログに出す。

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL