요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
.. SPDX-License-Identifier: GPL-2.0
======================================================
Texas Instruments CPSW switchdev based ethernet driver
======================================================
:Version: 2.0
Port renaming
=============
On older udev versions renaming of ethX to swXpY will not be automatically
supported
In order to rename via udev::
ip -d link show dev sw0p1 | grep switchid
SUBSYSTEM=="net", ACTION=="add", ATTR{phys_switch_id}==<switchid>, \
ATTR{phys_port_name}!="", NAME="sw0$attr{phys_port_name}"
Dual mac mode
=============
- The new (cpsw_new.c) driver is operating in dual-emac mode by default, thus
working as 2 individual network interfaces. Main differences from legacy CPSW
driver are:
- optimized promiscuous mode: The P0_UNI_FLOOD (both ports) is enabled in
addition to ALLMULTI (current port) instead of ALE_BYPASS.
So, Ports in promiscuous mode will keep possibility of mcast and vlan
filtering, which is provides significant benefits when ports are joined
to the same bridge, but without enabling "switch" mode, or to different
bridges.
- learning disabled on ports as it make not too much sense for
segregated ports - no forwarding in HW.
- enabled basic support for devlink.
::
devlink dev show
platform/48484000.switch
devlink dev param show
platform/48484000.switch:
name switch_mode type driver-specific
values:
cmode runtime value false
name ale_bypass type driver-specific
values:
cmode runtime value false
Devlink configuration parameters
================================
See Documentation/networking/devlink/ti-cpsw-switch.rst
Bridging in dual mac mode
=========================
The dual_mac mode requires two vids to be reserved for internal purposes,
which, by default, equal CPSW Port numbers. As result, bridge has to be
configured in vlan unaware mode or default_pvid has to be adjusted::
ip link add name br0 type bridge
ip link set dev br0 type bridge vlan_filtering 0
echo 0 > /sys/class/net/br0/bridge/default_pvid
ip link set dev sw0p1 master br0
ip link set dev sw0p2 master br0
or::
ip link add name br0 type bridge
ip link set dev br0 type bridge vlan_filtering 0
echo 100 > /sys/class/net/br0/bridge/default_pvid
ip link set dev br0 type bridge vlan_filtering 1
ip link set dev sw0p1 master br0
ip link set dev sw0p2 master br0
Enabling "switch"
=================
The Switch mode can be enabled by configuring devlink driver parameter
"switch_mode" to 1/true::
devlink dev param set platform/48484000.switch \
name switch_mode value 1 cmode runtime
This can be done regardless of the state of Port's netdev devices - UP/DOWN, but
Port's netdev devices have to be in UP before joining to the bridge to avoid
overwriting of bridge configuration as CPSW switch driver copletly reloads its
configuration when first Port changes its state to UP.
When both interfaces have joined the bridge - CPSW switch driver will enable
marking packets with offload_fwd_mark flag unless "ale_bypass=0"
All configuration is implemented via switchdev API.
Bridge setup
============
::
devlink dev param set platform/48484000.switch \
name switch_mode value 1 cmode runtime
ip link add name br0 type bridge
ip link set dev br0 type bridge ageing_time 1000
ip link set dev sw0p1 up
ip link set dev sw0p2 up
ip link set dev sw0p1 master br0
ip link set dev sw0p2 master br0
[*] bridge vlan add dev br0 vid 1 pvid untagged self
[*] if vlan_filtering=1. where default_pvid=1
Note. Steps [*] are mandatory.
On/off STP
==========
::
ip link set dev BRDEV type bridge stp_state 1/0
VLAN configuration
==================
::
bridge vlan add dev br0 vid 1 pvid untagged self <---- add cpu port to VLAN 1
Note. This step is mandatory for bridge/default_pvid.
Add extra VLANs
===============
1. untagged::
bridge vlan add dev sw0p1 vid 100 pvid untagged master
bridge vlan add dev sw0p2 vid 100 pvid untagged master
bridge vlan add dev br0 vid 100 pvid untagged self <---- Add cpu port to VLAN100
2. tagged::
bridge vlan add dev sw0p1 vid 100 master
bridge vlan add dev sw0p2 vid 100 master
bridge vlan add dev br0 vid 100 pvid tagged self <---- Add cpu port to VLAN100
FDBs
----
FDBs are automatically added on the appropriate switch port upon detection
Manually adding FDBs::
bridge fdb add aa:bb:cc:dd:ee:ff dev sw0p1 master vlan 100
bridge fdb add aa:bb:cc:dd:ee:fe dev sw0p2 master <---- Add on all VLANs
MDBs
----
MDBs are automatically added on the appropriate switch port upon detection
Manually adding MDBs::
bridge mdb add dev br0 port sw0p1 grp 239.1.1.1 permanent vid 100
bridge mdb add dev br0 port sw0p1 grp 239.1.1.1 permanent <---- Add on all VLANs
Multicast flooding
==================
CPU port mcast_flooding is always on
Turning flooding on/off on switch ports:
bridge link set dev sw0p1 mcast_flood on/off
Access and Trunk port
=====================
::
bridge vlan add dev sw0p1 vid 100 pvid untagged master
bridge vlan add dev sw0p2 vid 100 master
bridge vlan add dev br0 vid 100 self
ip link add link br0 name br0.100 type vlan id 100
Note. Setting PVID on Bridge device itself working only for
default VLAN (default_pvid).
NFS
===
The only way for NFS to work is by chrooting to a minimal environment when
switch configuration that will affect connectivity is needed.
Assuming you are booting NFS with eth1 interface(the script is hacky and
it's just there to prove NFS is doable).
setup.sh::
#!/bin/sh
mkdir proc
mount -t proc none /proc
ifconfig br0 > /dev/null
if [ $? -ne 0 ]; then
echo "Setting up bridge"
ip link add name br0 type bridge
ip link set dev br0 type bridge ageing_time 1000
ip link set dev br0 type bridge vlan_filtering 1
ip link set eth1 down
ip link set eth1 name sw0p1
ip link set dev sw0p1 up
ip link set dev sw0p2 up
ip link set dev sw0p2 master br0
ip link set dev sw0p1 master br0
bridge vlan add dev br0 vid 1 pvid untagged self
ifconfig sw0p1 0.0.0.0
udhchc -i br0
fi
umount /proc
run_nfs.sh:::
#!/bin/sh
mkdir /tmp/root/bin -p
mkdir /tmp/root/lib -p
cp -r /lib/ /tmp/root/
cp -r /bin/ /tmp/root/
cp /sbin/ip /tmp/root/bin
cp /sbin/bridge /tmp/root/bin
cp /sbin/ifconfig /tmp/root/bin
cp /sbin/udhcpc /tmp/root/bin
cp /path/to/setup.sh /tmp/root/bin
chroot /tmp/root/ busybox sh /bin/setup.sh
run ./run_nfs.sh
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
포트 이름, dual-MAC 모드와 devlink
1-58이 문서는 `GPL-2.0` 라이선스를 따릅니다.
Texas Instruments CPSW switchdev 기반 Ethernet 드라이버
버전 2.0
포트 이름 변경
오래된 udev 버전에서는 `ethX`를 `swXpY`로 자동 변경하는 기능을 지원하지 않습니다.
udev로 이름을 바꾸려면 `switchid`를 확인합니다.
ip -d link show dev sw0p1 | grep switchid
다음 udev 규칙으로 물리 switch와 port 이름을 이용해 새 이름을 만듭니다.
SUBSYSTEM=="net", ACTION=="add", ATTR{phys_switch_id}==<switchid>, \
ATTR{phys_port_name}!="", NAME="sw0$attr{phys_port_name}"
Dual-MAC 모드
새 `cpsw_new.c` 드라이버는 기본적으로 dual-EMAC 모드로 동작하여 두 개의 독립 네트워크 인터페이스를 제공합니다. 기존 CPSW 드라이버와 다른 점은 다음과 같습니다.
- 최적화한 promiscuous 모드: `ALE_BYPASS` 대신 현재 포트의 ALLMULTI와 두 포트의 `P0_UNI_FLOOD`를 켭니다. 따라서 같은 bridge에 있지만 switch 모드는 쓰지 않는 포트나 서로 다른 bridge의 포트도 multicast와 VLAN filtering을 유지할 수 있습니다.
- 분리된 포트는 하드웨어 forwarding을 하지 않으므로 port learning을 비활성화합니다.
- 기본적인 devlink 지원을 활성화합니다.
devlink 장치와 매개변수 출력 예
devlink dev show
platform/48484000.switch
devlink dev param show
platform/48484000.switch:
name switch_mode type driver-specific
values:
cmode runtime value false
name ale_bypass type driver-specific
values:
cmode runtime value false
`switch_mode`와 `ale_bypass`는 driver-specific runtime 매개변수이며 기본값은 모두 false입니다.
Devlink 구성 매개변수
`Documentation/networking/devlink/ti-cpsw-switch.rst`를 참조하십시오.
.. SPDX-License-Identifier: GPL-2.0
======================================================
Texas Instruments CPSW switchdev based ethernet driver
======================================================
:Version: 2.0
Port renaming
=============
On older udev versions renaming of ethX to swXpY will not be automatically
supported
In order to rename via udev::
ip -d link show dev sw0p1 | grep switchid
SUBSYSTEM=="net", ACTION=="add", ATTR{phys_switch_id}==<switchid>, \
ATTR{phys_port_name}!="", NAME="sw0$attr{phys_port_name}"
Dual mac mode
=============
- The new (cpsw_new.c) driver is operating in dual-emac mode by default, thus
working as 2 individual network interfaces. Main differences from legacy CPSW
driver are:
- optimized promiscuous mode: The P0_UNI_FLOOD (both ports) is enabled in
addition to ALLMULTI (current port) instead of ALE_BYPASS.
So, Ports in promiscuous mode will keep possibility of mcast and vlan
filtering, which is provides significant benefits when ports are joined
to the same bridge, but without enabling "switch" mode, or to different
bridges.
- learning disabled on ports as it make not too much sense for
segregated ports - no forwarding in HW.
- enabled basic support for devlink.
::
devlink dev show
platform/48484000.switch
devlink dev param show
platform/48484000.switch:
name switch_mode type driver-specific
values:
cmode runtime value false
name ale_bypass type driver-specific
values:
cmode runtime value false
Devlink configuration parameters
================================
See Documentation/networking/devlink/ti-cpsw-switch.rst
dual-MAC bridge 구성과 switch 모드
59-99Dual-MAC 모드의 bridging
dual-MAC 모드는 내부 용도로 두 VID를 예약해야 하며 기본적으로 CPSW port 번호와 같습니다. 따라서 bridge를 VLAN-unaware 모드로 구성하거나 `default_pvid`를 조정해야 합니다.
VLAN-unaware bridge 예
ip link add name br0 type bridge
ip link set dev br0 type bridge vlan_filtering 0
echo 0 > /sys/class/net/br0/bridge/default_pvid
ip link set dev sw0p1 master br0
ip link set dev sw0p2 master br0
VLAN filtering을 끄고 `default_pvid`를 0으로 설정한 뒤 두 포트를 bridge에 가입시킵니다.
별도의 기본 PVID 100을 사용하는 예
ip link add name br0 type bridge
ip link set dev br0 type bridge vlan_filtering 0
echo 100 > /sys/class/net/br0/bridge/default_pvid
ip link set dev br0 type bridge vlan_filtering 1
ip link set dev sw0p1 master br0
ip link set dev sw0p2 master br0
처음에는 VLAN filtering을 끈 상태에서 `default_pvid`를 100으로 바꾸고, 다시 filtering을 켠 뒤 포트를 가입시킵니다.
switch 활성화
devlink 드라이버 매개변수 `switch_mode`를 1 또는 true로 설정해 switch 모드를 활성화합니다.
devlink dev param set platform/48484000.switch \
name switch_mode value 1 cmode runtime
이 설정은 포트 netdev가 UP인지 DOWN인지와 무관하게 적용할 수 있지만, bridge에 가입시키기 전에 포트를 UP으로 만들어야 합니다. 첫 포트가 UP으로 바뀔 때 CPSW switch 드라이버가 구성을 완전히 다시 로드하기 때문에 순서가 다르면 bridge 구성이 덮어써질 수 있습니다.
두 인터페이스가 bridge에 가입하면 드라이버는 `ale_bypass=0`인 경우를 제외하고 패킷에 `offload_fwd_mark`를 표시합니다. 모든 구성은 switchdev API로 구현됩니다.
내부 VID 제약을 처리한 뒤 hardware forwarding을 활성화합니다.
Bridging in dual mac mode
=========================
The dual_mac mode requires two vids to be reserved for internal purposes,
which, by default, equal CPSW Port numbers. As result, bridge has to be
configured in vlan unaware mode or default_pvid has to be adjusted::
ip link add name br0 type bridge
ip link set dev br0 type bridge vlan_filtering 0
echo 0 > /sys/class/net/br0/bridge/default_pvid
ip link set dev sw0p1 master br0
ip link set dev sw0p2 master br0
or::
ip link add name br0 type bridge
ip link set dev br0 type bridge vlan_filtering 0
echo 100 > /sys/class/net/br0/bridge/default_pvid
ip link set dev br0 type bridge vlan_filtering 1
ip link set dev sw0p1 master br0
ip link set dev sw0p2 master br0
Enabling "switch"
=================
The Switch mode can be enabled by configuring devlink driver parameter
"switch_mode" to 1/true::
devlink dev param set platform/48484000.switch \
name switch_mode value 1 cmode runtime
This can be done regardless of the state of Port's netdev devices - UP/DOWN, but
Port's netdev devices have to be in UP before joining to the bridge to avoid
overwriting of bridge configuration as CPSW switch driver copletly reloads its
configuration when first Port changes its state to UP.
When both interfaces have joined the bridge - CPSW switch driver will enable
marking packets with offload_fwd_mark flag unless "ale_bypass=0"
All configuration is implemented via switchdev API.
Bridge, VLAN, FDB/MDB와 access/trunk 구성
100-194Bridge 설정
devlink dev param set platform/48484000.switch \
name switch_mode value 1 cmode runtime
ip link add name br0 type bridge
ip link set dev br0 type bridge ageing_time 1000
ip link set dev sw0p1 up
ip link set dev sw0p2 up
ip link set dev sw0p1 master br0
ip link set dev sw0p2 master br0
[*] bridge vlan add dev br0 vid 1 pvid untagged self
[*] if vlan_filtering=1. where default_pvid=1
Note. Steps [*] are mandatory.
switch 모드를 활성화하고 `br0`를 만든 뒤 ageing time을 1000으로 설정합니다. 두 포트를 UP으로 만들고 bridge에 가입시킵니다. `vlan_filtering=1`과 `default_pvid=1` 조합에서는 CPU 포트를 VLAN 1에 `pvid untagged self`로 추가하는 단계가 필수입니다.
STP 켜기와 끄기
ip link set dev BRDEV type bridge stp_state 1/0
VLAN 구성
CPU 포트를 VLAN 1에 추가하는 다음 단계는 bridge/default_pvid 구성을 위해 필수입니다.
bridge vlan add dev br0 vid 1 pvid untagged self
VLAN 100 untagged 구성
bridge vlan add dev sw0p1 vid 100 pvid untagged master
bridge vlan add dev sw0p2 vid 100 pvid untagged master
bridge vlan add dev br0 vid 100 pvid untagged self <---- Add cpu port to VLAN100
VLAN 100 tagged 구성
bridge vlan add dev sw0p1 vid 100 master
bridge vlan add dev sw0p2 vid 100 master
bridge vlan add dev br0 vid 100 pvid tagged self <---- Add cpu port to VLAN100
FDB
FDB 항목은 감지 시 적절한 switch 포트에 자동으로 추가됩니다. 수동 추가 시 `vlan 100`을 붙이면 해당 VLAN만, 생략하면 모든 VLAN에 적용됩니다.
bridge fdb add aa:bb:cc:dd:ee:ff dev sw0p1 master vlan 100
bridge fdb add aa:bb:cc:dd:ee:fe dev sw0p2 master <---- Add on all VLANs
MDB
MDB 항목도 감지 시 적절한 switch 포트에 자동으로 추가됩니다. `vid 100`을 붙이면 해당 VLAN만, 생략하면 모든 VLAN에 multicast group을 추가합니다.
bridge mdb add dev br0 port sw0p1 grp 239.1.1.1 permanent vid 100
bridge mdb add dev br0 port sw0p1 grp 239.1.1.1 permanent <---- Add on all VLANs
Multicast flooding
CPU 포트의 `mcast_flooding`은 항상 켜져 있습니다. switch 포트에서는 다음 명령으로 flooding을 제어합니다.
bridge link set dev sw0p1 mcast_flood on/off
Access 및 trunk 포트
bridge vlan add dev sw0p1 vid 100 pvid untagged master
bridge vlan add dev sw0p2 vid 100 master
bridge vlan add dev br0 vid 100 self
ip link add link br0 name br0.100 type vlan id 100
`sw0p1`은 VLAN 100의 untagged access 포트, `sw0p2`는 tagged trunk 포트입니다. CPU 포트를 VLAN 100에 가입시키고 `br0.100` VLAN 인터페이스를 만듭니다. Bridge 장치 자체의 PVID 설정은 기본 VLAN인 `default_pvid`에만 적용됩니다.
switch 포트와 CPU 포트에 사용하는 플래그를 구분합니다.
Bridge setup
============
::
devlink dev param set platform/48484000.switch \
name switch_mode value 1 cmode runtime
ip link add name br0 type bridge
ip link set dev br0 type bridge ageing_time 1000
ip link set dev sw0p1 up
ip link set dev sw0p2 up
ip link set dev sw0p1 master br0
ip link set dev sw0p2 master br0
[*] bridge vlan add dev br0 vid 1 pvid untagged self
[*] if vlan_filtering=1. where default_pvid=1
Note. Steps [*] are mandatory.
On/off STP
==========
::
ip link set dev BRDEV type bridge stp_state 1/0
VLAN configuration
==================
::
bridge vlan add dev br0 vid 1 pvid untagged self <---- add cpu port to VLAN 1
Note. This step is mandatory for bridge/default_pvid.
Add extra VLANs
===============
1. untagged::
bridge vlan add dev sw0p1 vid 100 pvid untagged master
bridge vlan add dev sw0p2 vid 100 pvid untagged master
bridge vlan add dev br0 vid 100 pvid untagged self <---- Add cpu port to VLAN100
2. tagged::
bridge vlan add dev sw0p1 vid 100 master
bridge vlan add dev sw0p2 vid 100 master
bridge vlan add dev br0 vid 100 pvid tagged self <---- Add cpu port to VLAN100
FDBs
----
FDBs are automatically added on the appropriate switch port upon detection
Manually adding FDBs::
bridge fdb add aa:bb:cc:dd:ee:ff dev sw0p1 master vlan 100
bridge fdb add aa:bb:cc:dd:ee:fe dev sw0p2 master <---- Add on all VLANs
MDBs
----
MDBs are automatically added on the appropriate switch port upon detection
Manually adding MDBs::
bridge mdb add dev br0 port sw0p1 grp 239.1.1.1 permanent vid 100
bridge mdb add dev br0 port sw0p1 grp 239.1.1.1 permanent <---- Add on all VLANs
Multicast flooding
==================
CPU port mcast_flooding is always on
Turning flooding on/off on switch ports:
bridge link set dev sw0p1 mcast_flood on/off
Access and Trunk port
=====================
::
bridge vlan add dev sw0p1 vid 100 pvid untagged master
bridge vlan add dev sw0p2 vid 100 master
bridge vlan add dev br0 vid 100 self
ip link add link br0 name br0.100 type vlan id 100
Note. Setting PVID on Bridge device itself working only for
default VLAN (default_pvid).
NFS 부팅 환경에서 switch 재구성
195-242NFS
연결성에 영향을 주는 switch 구성이 필요할 때 NFS를 유지하는 유일한 방법은 최소 환경으로 chroot하여 작업하는 것입니다. 다음 예는 `eth1` 인터페이스로 NFS 부팅했다고 가정합니다. 스크립트는 임시 방편이며 NFS에서도 구성이 가능함을 보이기 위한 예입니다.
`setup.sh`
#!/bin/sh
mkdir proc
mount -t proc none /proc
ifconfig br0 > /dev/null
if [ $? -ne 0 ]; then
echo "Setting up bridge"
ip link add name br0 type bridge
ip link set dev br0 type bridge ageing_time 1000
ip link set dev br0 type bridge vlan_filtering 1
ip link set eth1 down
ip link set eth1 name sw0p1
ip link set dev sw0p1 up
ip link set dev sw0p2 up
ip link set dev sw0p2 master br0
ip link set dev sw0p1 master br0
bridge vlan add dev br0 vid 1 pvid untagged self
ifconfig sw0p1 0.0.0.0
udhchc -i br0
fi
umount /proc
스크립트는 chroot 안에서 `/proc`을 마운트하고 `br0`가 없으면 bridge와 VLAN filtering을 구성합니다. `eth1`을 내린 뒤 `sw0p1`로 이름을 바꾸고 두 포트를 올려 bridge에 가입시킵니다. CPU 포트를 VLAN 1에 추가하고 기존 포트 주소를 지운 다음 `br0`에서 DHCP client를 실행합니다. 마지막에 `/proc`을 unmount합니다.
`run_nfs.sh`
#!/bin/sh
mkdir /tmp/root/bin -p
mkdir /tmp/root/lib -p
cp -r /lib/ /tmp/root/
cp -r /bin/ /tmp/root/
cp /sbin/ip /tmp/root/bin
cp /sbin/bridge /tmp/root/bin
cp /sbin/ifconfig /tmp/root/bin
cp /sbin/udhcpc /tmp/root/bin
cp /path/to/setup.sh /tmp/root/bin
chroot /tmp/root/ busybox sh /bin/setup.sh
실행 스크립트는 `/tmp/root` 아래에 최소 root 환경을 만들고 `/lib`, `/bin`과 필요한 `ip`, `bridge`, `ifconfig`, `udhcpc`, `setup.sh`를 복사합니다. 그다음 `chroot /tmp/root/ busybox sh /bin/setup.sh`로 격리된 환경에서 switch 구성을 수행합니다.
실행
./run_nfs.sh
현재 root filesystem의 네트워크 의존성을 피하기 위해 최소 chroot에서 작업합니다.
NFS
===
The only way for NFS to work is by chrooting to a minimal environment when
switch configuration that will affect connectivity is needed.
Assuming you are booting NFS with eth1 interface(the script is hacky and
it's just there to prove NFS is doable).
setup.sh::
#!/bin/sh
mkdir proc
mount -t proc none /proc
ifconfig br0 > /dev/null
if [ $? -ne 0 ]; then
echo "Setting up bridge"
ip link add name br0 type bridge
ip link set dev br0 type bridge ageing_time 1000
ip link set dev br0 type bridge vlan_filtering 1
ip link set eth1 down
ip link set eth1 name sw0p1
ip link set dev sw0p1 up
ip link set dev sw0p2 up
ip link set dev sw0p2 master br0
ip link set dev sw0p1 master br0
bridge vlan add dev br0 vid 1 pvid untagged self
ifconfig sw0p1 0.0.0.0
udhchc -i br0
fi
umount /proc
run_nfs.sh:::
#!/bin/sh
mkdir /tmp/root/bin -p
mkdir /tmp/root/lib -p
cp -r /lib/ /tmp/root/
cp -r /bin/ /tmp/root/
cp /sbin/ip /tmp/root/bin
cp /sbin/bridge /tmp/root/bin
cp /sbin/ifconfig /tmp/root/bin
cp /sbin/udhcpc /tmp/root/bin
cp /path/to/setup.sh /tmp/root/bin
chroot /tmp/root/ busybox sh /bin/setup.sh
run ./run_nfs.sh
요약·해설
cpsw_switchdev.rst:1-242새 CPSW 드라이버는 기본 dual-EMAC 모드에서 두 포트를 분리하고 learning을 끕니다. switch 모드로 바꾸려면 내부 예약 VID와 bridge의 `default_pvid` 충돌을 먼저 해소해야 하며, NFS root를 사용하는 시스템은 최소 chroot 안에서 bridge를 재구성해야 연결 손실 위험을 줄일 수 있습니다.
기본 dual-EMAC과 switchdev 모드의 동작 차이입니다.
root filesystem 연결을 끊지 않도록 별도 실행 환경을 준비합니다.