# 네트워크 네임스페이스: 새 네트워크 환경의 상태를 나누는 방법

v6.18.37 / net/core/net_namespace.c

네트워크 네임스페이스는 인터페이스·라우팅·소켓 관련 네트워크 상태를 서로 분리해 관리하게 합니다. 새 struct net만 할당한다고 모든 하위 기능이 준비되지는 않습니다. 등록된 pernet_operations를 따라 각 기능의 전용 상태를 할당하고 초기화해야 하며, ops_init은 그중 한 기능을 한 네임스페이스에 설치하는 전체 절차입니다.

## ops_init

```c

static int ops_init(const struct pernet_operations *ops, struct net *net)
{
	struct net_generic *ng;
	int err = -ENOMEM;
	void *data = NULL;

	if (ops->id) {
		data = kzalloc(ops->size, GFP_KERNEL);
		if (!data)
			goto out;

		err = net_assign_generic(net, *ops->id, data);
		if (err)
			goto cleanup;
	}
	err = 0;
	if (ops->init)
		err = ops->init(net);
	if (!err)
		return 0;

	if (ops->id) {
		ng = rcu_dereference_protected(net->gen,
					       lockdep_is_held(&pernet_ops_rwsem));
		ng->ptr[*ops->id] = NULL;
	}

cleanup:
	kfree(data);

out:
	return err;
}

```

### 120행

```c

static int ops_init(const struct pernet_operations *ops, struct net *net)

```

한 네트워크 기능의 초기화 규칙 ops를 특정 네임스페이스 net에 적용합니다.

### 122행

```c

	struct net_generic *ng;

```

net의 generic 포인터 표를 다룰 지역변수입니다.

### 123행

```c

	int err = -ENOMEM;

```

메모리 할당이 바로 실패하면 반환할 -ENOMEM을 기본값으로 둡니다.

### 124행

```c

	void *data = NULL;

```

아직 할당한 데이터가 없음을 NULL로 나타냅니다.

### 126행

```c

	if (ops->id) {

```

이 기능이 네임스페이스별 generic 데이터 슬롯을 요구하는지 확인합니다.

### 127행

```c

		data = kzalloc(ops->size, GFP_KERNEL);

```

ops->size만큼 0으로 채운 메모리를 할당합니다. GFP_KERNEL 경로는 필요한 경우 잠들 수 있습니다.

### 128행

```c

		if (!data)

```

메모리 할당 실패를 검사합니다.

### 129행

```c

			goto out;

```

할당한 것이 없으므로 별도 해제 없이 오류 반환 위치로 갑니다.

### 131행

```c

		err = net_assign_generic(net, *ops->id, data);

```

기능 id에 해당하는 net의 슬롯에 새 데이터를 설치합니다.

### 132행

```c

		if (err)

```

슬롯 확장이나 설치가 실패했는지 확인합니다.

### 133행

```c

			goto cleanup;

```

설치하지 못한 메모리를 해제하는 위치로 갑니다.

### 135행

```c

	err = 0;

```

기능 초기화 함수를 호출하지 않는 경우에도 성공할 수 있도록 결과를 0으로 바꿉니다.

### 136행

```c

	if (ops->init)

```

이 기능이 init 콜백을 제공하는지 확인합니다.

### 137행

```c

		err = ops->init(net);

```

해당 네임스페이스를 넘겨 기능별 초기화를 수행합니다.

### 138행

```c

	if (!err)

```

초기화가 성공했거나 콜백이 없어서 정상인지를 확인합니다.

### 139행

```c

		return 0;

```

성공한 경우 데이터는 네임스페이스가 계속 사용하므로 해제하지 않습니다.

### 141행

```c

	if (ops->id) {

```

실패한 초기화 전에 generic 슬롯을 설치한 경로인지 확인합니다.

### 142행

```c

		ng = rcu_dereference_protected(net->gen,

```

보호된 조건에서 net의 generic 포인터 표를 얻습니다.

### 143행

```c

					       lockdep_is_held(&pernet_ops_rwsem));

```

pernet_ops_rwsem을 보유한 상태라는 잠금 검증 조건을 RCU 접근에 전달합니다.

### 144행

```c

		ng->ptr[*ops->id] = NULL;

```

곧 해제할 데이터를 가리키던 슬롯을 NULL로 비웁니다.

### 147행

```c

cleanup:

```

슬롯 설치 실패와 기능 초기화 실패가 공유하는 메모리 정리 위치입니다.

### 148행

```c

	kfree(data);

```

앞서 할당한 전용 데이터를 해제합니다. NULL이면 아무것도 해제하지 않습니다.

### 150행

```c

out:

```

오류를 호출자에게 돌려줄 공통 위치입니다.

### 151행

```c

	return err;

```

메모리 또는 기능 초기화 단계에서 얻은 오류를 반환합니다.

