레이블이 Linux-init/systemd인 게시물을 표시합니다. 모든 게시물 표시
레이블이 Linux-init/systemd인 게시물을 표시합니다. 모든 게시물 표시

8/09/2020

systemd 의 logrotate 분석 과 Timer 사용법

1. systemd의 logrotate 기본구성 과 분석

syslog가 log 파일을 생성을 한다고 하면, 매번 Log를 주기적으로 backup을 하여 보관의 필요성을 느낄 것이며, 이를 위해서 사용되어지는 program이 logrotate이다 

만약 기본설치가 되어있다면, /etc/logrotate.conf 설정이 존재할 것이다. 
다만 logrotate가 자동으로 실행되는 program이 아니며, Linux Filesystem에 따라 sysvInit 일 경우는  cron 을 이용하여 주기적으로 호출되고, 
systemd일 경우는 timer를 이용하여 이를 주기적으로 호출되어 동작가능하다 


  • syslog 관련내용 
logrotate를 알기전에 syslogd에 대해 알자.
  https://ahyuo79.blogspot.com/2019/04/syslog.html


  • 기본설정파일 
  1. /etc/logrotate.conf  : 
  2. /etc/logrotate.d/btmp : 기본으로 설치됨 
  3. /etc/logrotate.d/wtmp


  • systemd의 timer 사용시 분석할 파일 
  1. /lib/systemd/system/logrotate.timer
  2. /lib/systemd/system/logrotate.service
  3. /etc/systemd/system/timers.target.wants/logrotate.timer  (Timer가 enable일 경우 존재)



1.1 logrotate 의 timer 와 service 분석 


  • logrotate 의 service 와 timer 분석

반드시 logrotate.service 와 logrotate.timer 의 prefix name이 logrotate.는 이름으로 동일해야 제대로 동작한다
logrotate.service는  logrotate.timer가 주기적으로 호출되어 를 구동하는 구조로 동작되어있기 때문에, systemd의 timer 현재 systemctl enable이 된 상태이다.


  • logrotate.timer 구조 파악  
분석으로 보면 매일 밤 12시, 즉 0시에 동작이 되며, Timer를 확인하는 주기는 12시간으로 정확성을 많이 떨어트리지만, Persistent를 이용

$ cat /lib/systemd/system/logrotate.timer 
[Unit]
Description=Daily rotation of log files
Documentation=man:logrotate(8) man:logrotate.conf(5)

[Timer]
OnCalendar=daily
AccuracySec=12h
Persistent=true

[Install]
WantedBy=timers.target
// systemctl enable logrotate.timer 할 경우  아래 link 생성됨
// systemctl disable logrotate.timer 할 경우 아래 link 제거됨

// timers.target.wants에 timer가 존재하는 것은 현재 enable 되는 상태
$ ls -al /etc/systemd/system/timers.target.wants/logrotate.timer
/etc/systemd/system/timers.target.wants/logrotate.timer -> /lib/systemd/system/logrotate.timerrotate.timer
$ systemctl status logrotate.timer // 매일 0시에 Trigger되어 동작함 $ systemctl is-enabled logrotate.timer // logrotate.timer enable enabled

systemd.timer 의 OnCalendar 설정정보 시간설정방법
onCalendar Time 설정을 보면 전부 0시기준으로 동작 
daily → *-*-* 00:00:00

시간동기화문제
OnCalendar 일반적으로 사용할 경우 time-sync.target 이후에 설정하도록 의존성을 넣는다고한다. 
  https://www.freedesktop.org/software/systemd/man/systemd.timer.html#Default%20Dependencies


기타 다른예제 (좋은예제)


  • 상위 timer에 의해 실행되는 logrotate.service 
기존의 Service 구조와 다르게 [Install] Section 이 없으며, *wants 및 에 위치 하지도 않는다
현재 systemctl disable logrotate.service 인 상태이지만 상위 timer가 구동을 시켜준다.

$ cat /lib/systemd/system/logrotate.service
[Unit]
Description=Rotate log files
Documentation=man:logrotate(8) man:logrotate.conf(5)
RequiresMountsFor=/var/log
ConditionACPower=true

[Service]
Type=oneshot
ExecStart=/usr/sbin/logrotate /etc/logrotate.conf

# performance options
Nice=19
IOSchedulingClass=best-effort
IOSchedulingPriority=7

# hardening options
#  details: https://www.freedesktop.org/software/systemd/man/systemd.exec.html
#  no ProtectHome for userdir logs
#  no PrivateNetwork for mail deliviery
#  no ProtectKernelTunables for working SELinux with systemd older than 235
MemoryDenyWriteExecute=true
PrivateDevices=true
PrivateTmp=true
ProtectControlGroups=true
ProtectKernelModules=true
ProtectSystem=full
RestrictRealtime=true

$ systemctl status logrotate.service // logrotate.service 동작시간 확인 

$ systemctl is-enabled logrotate.service // logrotate.timer에 의해 동작 
static

1.2 logrotate 설정분석 


기본적으로 설정은 /etc/logrotate.conf에서 하지만, 확장설정이 가능하므로, 
아래와 같이 include를 사용하여 /etc/logrotate.d 안에 있는 존재하는 모든 파일도 허용한다

  • 기본설정구성 
$ cat /etc/logrotate.conf
# see "man logrotate" for details
# rotate log files weekly
weekly

# keep 4 weeks worth of backlogs
rotate 4

# create new (empty) log files after rotating old ones
create

# use date as a suffix of the rotated file
dateext

# uncomment this if you want your log files compressed
#compress

# packages drop log rotation information into this directory
include /etc/logrotate.d

# system-specific logs may be also be configured here.

mail command가 지원되며 e-mail에 log 정보도 같이 수신받을 수 있다. 

  • /var/log/btmp 설정 
실패한 Login 정보 (lastb 명령어로 확인)
$ cat /etc/logrotate.d/btmp
# no packages own btmp -- we'll rotate it here
/var/log/btmp {
    missingok
    monthly
    create 0600 root utmp
    rotate 1
}

  • /var/log/wtmp 설정 
사용자의 Login/out과 시스템정보를 관리 (last 명령어로 확인)
$ cat /etc/logrotate.d/wtmp
# no packages own wtmp -- we'll rotate it here
/var/log/wtmp {
    missingok
    monthly
    create 0664 root utmp
    minsize 1M                # 상위 monthly 와 별개로 사이즈가 넘으면 rotate 
    rotate 1
}

last 와 lastb

  • /var/log/message 와 /var/log/test 설정 예 

$ cat /etc/logrotate.d/test1   // kill -HUP  syslogd 재시작 
/var/log/messages /var/log/test {
    missingok              ## 로그파일을 없어도, 에러없이 진행 (nomissingok 로그파일 없으면 에러발생 default) 
    monthly
    rotate 5
    dateext                ## 저장된 log에 날짜표시 
#   ifempty                ## ifempty 이 default (log파일 비어 있어도 rotate 진행)    
#   nosharedscripts        ## nosharedscripts 이 default 이며, 상위 /var/log/test*이면 여러개를 다 실행 
    postrotate             ## logroate가 실행된 후 script로 kill로 Signal 전송하여 Refresh 
        /bin/kill -HUP 'cat /var/run/syslogd.pid 2> /dev/null' 2> /dev/null
    endscript

$ kill -l
HUP INT QUIT ILL TRAP ABRT BUS FPE KILL USR1 SEGV USR2 PIPE ALRM TERM STKFLT CHLD CONT STOP TSTP TTIN TTOU URG XCPU XFSZ VTALRM PROF WINCH IO PWR SYS RTMIN RTMIN+1 RTMIN+2 RTMIN+3 RTMIN+4 RTMIN+5 RTMIN+6 RTMIN+7 RTMIN+8 RTMIN+9 RTMIN+10 RTMIN+11 RTMIN+12 RTMIN+13 RTMIN+14 RTMIN+15 RTMAX-14 RTMAX-13 RTMAX-12 RTMAX-11 RTMAX-10 RTMAX-9 RTMAX-8 RTMAX-7 RTMAX-6 RTMAX-5 RTMAX-4 RTMAX-3 RTMAX-2 RTMAX-1 RTMAX
## 1 -HUP SIGHUP  Refresh
##-2 INT  SIGINT Interrupt (Ctrl+C)
##-3 QUIT SIGQUIT Quit (Ctrl+z)  (이하 생략)

}

Process에 문제가 있어서 다시 시작하고자 할 때에는 SIGHUP, SIGTERM, SIGKILL
kill 명령어 
  https://ko.wikipedia.org/wiki/Kill
  https://en.wikipedia.org/wiki/SIGHUP


$ cat /etc/logrotate.d/test2   // kill -HUP  syslogd 재시작 
/var/log/test {
    missingok
    daily
    rotate 10
    dateext
    sharedscripts          ## sharedscripts /var/log/news/*  같이 log가 여러개 중복될때 한번만실행 
    postrotate
         /bin/kill -HUP 'cat /var/run/syslogd.pid 2> /dev/null' 2> /dev/null
    endscript
}

/var/log/messages {
    missingok
    daily
    rotate 20
    dateext    
    postrotate
        /bin/kill -HUP 'cat /var/run/syslogd.pid 2> /dev/null' 2> /dev/null
    endscript
}

$ cat /etc/logrotate.d/test3   // kill -HUP  syslogd 재시작 

/var/log/messages {
    rotate 3
    minsize 1M
    sharedscripts
    postrotate
        /bin/kill -HUP 'cat /var/run/syslogd.pid 2> /dev/null' 2> /dev/null
    endscript
}

$ cat /var/lib/logrotate.status  // 각 logroate가 된 후 상태확인 
logrotate state -- version 2
"/var/log/test" 2020-08-06-0:0:58
"/var/log/wtmp" 2020-07-10-11:0:0
"/var/log/btmp" 2020-07-10-11:0:0
"/var/log/message" 2020-07-10-11:0:0


logrotate(cron) and syslogd
  http://heart4u.co.kr/tblog/370
  



2. systemd 의 timer 사용방법


SysVinit에서는 cron을 사용했지만, systemd에서는 Timer를 사용해서 본인이 원하는 것을 주기적으로 실행해야하며, 
systemd의 timer는 monotonic timercalendar time(Realtime)으로 구분이되는데, 거의 monotonic timer를 많이 사용할 것이므로 아래로 처럼 구성한다


  • 현재 Timer 구성확인
$ systemctl list-timers   // Timer 상태확인 
or
$ systemctl list-timers --all | cat   // 모든 Timer 상태확인 (inactive timer 포함)
or
$ systemctl list-timers | cat
NEXT                         LEFT     LAST                         PASSED  UNIT                         ACTIVATES
Tue 2020-07-17 17:44:51 KST  7h left  Mon 2020-07-16 17:44:51 KST  16h ago systemd-tmpfiles-clean.timer systemd-tmpfiles-clean.service
Wed 2020-07-18 00:00:00 KST  14h left Tue 2020-07-17 00:00:36 KST  9h ago  logrotate.timer              logrotate.service

  • monotonic timer 예제
 $ cat monotonic.timer   // booting 후 15분 후 동작후 매주 돌아가는 timer (미테스트)
[Unit]
Description=Run foo weekly and on boot

[Timer]
OnBootSec=15min
OnUnitActiveSec=1w 

[Install]
WantedBy=timers.target 

  • realtime timer 예제
 $ realtime.timer    // 일주일에 한번  12:00am on Monday 동작 (미테스트) 
[Unit]
Description=Run foo weekly

[Timer]
OnCalendar=weekly
Persistent=true

# Persistent          true이며, Timer가 실행한 서비스 Trigger정보를 Disk가 저장후 Timer가 동작할때, 즉각 Service 동작하도록 설정 

[Install]
WantedBy=timers.target

출처 

Realtime 으로 Monotonic Timer 구현 


2.1 systemd 의 TEST Timer 구성 


Timer를 잘 사용하기 위해서 monotonic timer 기반으로 구성 후 간단한 예제를 만들고, 이를 테스트 할 수 있는 shell script 와 함께 
내부의 환경변수 값들을 변경해보면 직접 테스트 진행. 

  • Test Timer 전체구성 
  1. /usr/bin/foo.sh 
  2. /lib/systemd/system/foo.timer
  3. /lib/systemd/system/foo.service 

  • timer로 실행될 service의 shell script 작성
$ vi /usr/bin/foo.sh   // 주기적으로 실행할 Shell Script 
#!/bin/sh
# Author: Jeonghun
#

WAIT_100MS() {
    sleep 0.1
}
# NOW 현재시간 
# UPTIME 은 부팅후 시간 측정용 1st arg (Booting 후 Sec)  2nd arg (Idle Time Sec) 
NOW=$(date +"%H:%M:%S")
UPTIME=`cat /proc/uptime`
echo -e "\x1b[1;93m *** TIMER $NOW  $UPTIME  \x1b[0m" > /dev/kmsg

$ chmod +x /usr/bin/foo.sh  // 실행권한 설정 

  • systemd 의 foo.timer 작성 (sample)
$ vi /etc/systemd/system/foo.timer
or
$ vi /lib/systemd/system/foo.timer
[Unit]
Description=Run 3 Secs foo timer from 1 min after boot

[Timer]
OnBootSec=1min
OnUnitActiveSec=3s
#OnActiveSec=3s

[Install]
WantedBy=timers.target

#
#
# [Timer] Section 
#
# 반드시 Monotonic Timer로 설정시 아래 설정을 포함을 해야하며, 중복 설정도 가능 
# OnActiveSec=, OnBootSec=, OnStartupSec=, OnUnitActiveSec=, OnUnitInactiveSec= 
# 
# 상위 설정을 한 후 세부 설정을 별도로 진행


$ systemctl enable foo.timer
Created symlink /etc/systemd/system/timers.target.wants/foo.timer → /etc/systemd/system/foo.timer.

$ ls -al /etc/systemd/system/timers.target.wants/foo.timer   // 생성된 링크확인 

  https://www.freedesktop.org/software/systemd/man/systemd.timer.html

  • systemd 의 timer 에 의해 실행될 service 설정
$ vi /etc/systemd/system/foo.service    
or
$ vi /lib/systemd/system/foo.service  // 상위 foo.timer에 의해 실행되므로 별도로 service 설정을 안해도 됨 
[Unit]
Description=TEST
Requires=local-fs.target
After=local-fs.target

[Service]
Type=simple
ExecStart=/usr/bin/foo.sh

Test Timer 구성참조
  https://coderoad.ru/9619362/%D0%97%D0%B0%D0%BF%D1%83%D1%81%D0%BA-a-cron-%D0%BA%D0%B0%D0%B6%D0%B4%D1%8B%D0%B5-30-%D1%81%D0%B5%D0%BA%D1%83%D0%BD%D0%B4 

AccuracySec=의 이해 

2.2 TEST(foo.timer) 설정 변경 테스트  

Timer의 설정의 의미를 알기 위해서 foo.timer의 설정값에 변경하여 개별 테스트 진행하며, 아래와 같이 그 결과도 알아본다.


  • foo.timer 수정 후 테스트 및 분석 (전체 2번실행)

[Timer]
OnBootSec=1min
OnActiveSec=3s
# OnBootSec          Booting 후 실행되는 Timer 설정 1분이며, OnStartupSec= 값도 동일하게 설정
# OnStartupSec       OnBootSec 거의 유사하지만 다른점은 service manager가 동작한 시점부터라고함 (아직 정확한 차이는 모름)
# OnActiveSec        Timer 자신이 Active 된 순간의 시간이라고 하는데,  
# AccuracySec        Timer를 확인하는 주기 미설정시 기본 1분 
// 1st TEST, 상위설정값 TEST 많이 다르며, 전체 2번만 동작  
 *** TIMER 14:55:59  14.64 0.77               // OnActiveSec 14초 Timer가 Active되는 순간 
 *** TIMER 14:56:55  70.89 47.92              // OnBootSec 70초 (AccuracySec 1분, 정확성이 떨어짐) 

// 2nd TEST, 상위설정값 TEST 많이 다르며, 전체 2번만 동작  
 *** TIMER 15:21:56  14.81 0.90
 *** TIMER 15:22:53  72.45 50.00              // OnBootSec 72초 (AccuracySec 1분, 정확성이 떨어짐) 

  • foo.timer 수정 후 테스트 및 분석 (전체 1번실행)

[Timer]
OnBootSec=1min
AccuracySec=3s
# AccuracySec        Timer를 확인하는 주기를 설정이며, 기본은 1분이지만,3초로 변경, 즉 정확성을 높임  
// 1st TEST 상위 설정값대로 동작하며, 전체 1번만 동작   
 *** TIMER 15:33:52  62.05 39.34                // OnBootSec 62초 (AccuracySec 3초 이내) 
 
// 2nd TEST 상위 설정값대로 동작하며, 전체 1번만 동작   
 *** TIMER 15:38:43  62.95 40.51                // OnBootSec 62초 (AccuracySec 3초 이내)       



  • foo.timer 수정 후 테스트 및 분석 (계속실행)
[Timer]
OnBootSec=1min
OnUnitActiveSec=3s
# OnBootSec          Booting 후 실행되는 Timer 설정 1분이며, OnStartupSec= 값도 동일하게 설정 
# OnUnitActiveSec    마지막(OnBootSec)에 Timer가 실행한 Unit(즉 서비스) Active가 되었을때 기준으로 3초 설정 
# AccuracySec        Timer를 확인하는 주기 미설정시 기본 1분 
// 1st TEST, 상위설정값과 많이 다르지만 계속동작                         
 *** TIMER 14:51:42  73.61 50.83           // OnBootSec 73초 (AccuracySec 때문에 정확성이 떨어짐) 
 *** TIMER 14:52:19  111.12 87.40          // OnUnitActiveSec 111-73= 38초 
 *** TIMER 14:52:43  134.63 110.23         // OnUnitActiveSec 134-111= 23초 
 *** TIMER 14:53:01  153.08 128.23         // OnUnitActiveSec 153-134= 19초 
 *** TIMER 14:53:19  171.37 146.09

// 2nd TEST, 상위설정값과 많이 다르지만 계속동작       
 *** TIMER 15:02:58  78.25 55.14            // OnBootSec 78초 
 *** TIMER 15:03:32  111.50 87.60
 *** TIMER 15:04:04  143.61 118.85
 *** TIMER 15:04:19  158.80 133.61
 *** TIMER 15:04:33  173.25 147.56


  • foo.timer 수정 후 테스트 및 분석 (계속실행)

[Timer]
OnBootSec=1min
OnUnitActiveSec=3s
AccuracySec=3s
# OnUnitActiveSec    마지막(OnBootSec)에 Timer가 실행한 Unit(즉 서비스) Active가 되었을때 기준으로 3초 설정 
# OnUnitInactiveSec  마지막(OnBootSec)에 Timer가 실행한 Unit(즉 서비스) inActive가 되었을때 기준으로 시간설정 
# AccuracySec        Timer를 확인하는 주기를 설정이며, 기본은 1분이지만,3초로 변경, 즉 정확성을 높임  
// 1st TEST 상위 설정값과 유사하게 동작 (3~6 초)   
 *** TIMER 15:14:11  60.66 37.90              // OnBootSec 60초 (AccuracySec 3초 이내) 
 *** TIMER 15:14:17  66.65 43.66              // OnUnitActiveSec 3초 (AccuracySec 3초 이내) 
 *** TIMER 15:14:21  70.65 47.49
 *** TIMER 15:14:27  76.65 53.23
 *** TIMER 15:14:31  80.65 57.03
 *** TIMER 15:14:37  86.64 62.80
 *** TIMER 15:14:41  90.64 66.65
 *** TIMER 15:14:47  96.65 72.41
 *** TIMER 15:14:51  100.64 76.23
 *** TIMER 15:14:57  106.65 81.98
 *** TIMER 15:15:01  110.64 85.82
 *** TIMER 15:15:07  116.65 91.63
 *** TIMER 15:15:11  120.65 95.41
 *** TIMER 15:15:14  123.70 98.31
 *** TIMER 15:15:20  129.65 103.99
 
// 2nd TEST 상위 설정값과 유사하게 동작 (3~6 초)   
 *** TIMER 15:18:38  62.95 40.17             // OnBootSec 62초 (AccuracySec 3초 이내) 
 *** TIMER 15:18:44  68.94 45.94             // OnUnitActiveSec 3초 (AccuracySec 3초 이내) 
 *** TIMER 15:18:50  74.94 51.72
 *** TIMER 15:18:54  78.95 55.56
 *** TIMER 15:19:00  84.95 61.33
 *** TIMER 15:19:04  88.95 65.16
 *** TIMER 15:19:10  94.95 70.94
 *** TIMER 15:19:14  98.94 74.77
 *** TIMER 15:19:20  104.94 80.57
 *** TIMER 15:19:24  108.94 84.39
 *** TIMER 15:19:30  114.95 90.17
 *** TIMER 15:19:34  118.94 94.01
 *** TIMER 15:19:40  124.94 99.87
 *** TIMER 15:19:44  128.95 103.73

  • foo.timer 수정 후 테스트 및 분석 (계속실행)

[Timer]
OnBootSec=1min
OnUnitActiveSec=1s
AccuracySec=3s
# OnUnitActiveSec    마지막(OnBootSec)에 Timer가 실행한 Unit(즉 서비스) Active가 되었을때 기준으로 1초 설정 
# AccuracySec        Timer를 확인하는 주기를 설정이며, 기본은 1분이지만,3초로 변경, 즉 정확성을 높임  
// 1st TEST 상위 설정값과 가장유사하게 동작 2-4초 간격   
 *** TIMER 15:27:55  61.66 38.97               // OnBootSec 61초 (AccuracySec 3초 이내) 
 *** TIMER 15:27:59  65.65 42.82               // OnUnitActiveSec 1초 (AccuracySec 3초 이내) 
 *** TIMER 15:28:03  69.65 46.64
 *** TIMER 15:28:05  71.66 48.50
 *** TIMER 15:28:09  75.65 52.26
 *** TIMER 15:28:13  79.65 56.07
 *** TIMER 15:28:15  81.65 57.98
 *** TIMER 15:28:19  85.65 61.80
 *** TIMER 15:28:23  89.66 65.65
 *** TIMER 15:28:25  91.65 67.52
 *** TIMER 15:28:29  95.65 71.35
 *** TIMER 15:28:33  99.66 75.17
 *** TIMER 15:28:35  101.65 77.06
 *** TIMER 15:28:39  105.65 80.92
 *** TIMER 15:28:43  109.65 84.74
 *** TIMER 15:28:45  111.65 86.63
 *** TIMER 15:28:49  115.66 90.47
 *** TIMER 15:28:53  119.65 94.29
 *** TIMER 15:28:55  121.66 96.18
 *** TIMER 15:28:59  125.66 99.99
 
// 2nd TEST 상위 설정값과 가장유사하게 동작   
 *** TIMER 15:30:39  63.05 40.48               // OnBootSec 63초 (AccuracySec 3초 이내) 
 *** TIMER 15:30:43  67.04 44.33               // OnUnitActiveSec 1초 (AccuracySec 3초 이내) 
 *** TIMER 15:30:47  71.04 48.17
 *** TIMER 15:30:50  74.04 51.06
 *** TIMER 15:30:54  78.04 54.87
 *** TIMER 15:30:58  82.04 58.69
 *** TIMER 15:30:59  83.30 59.84
 *** TIMER 15:31:03  87.04 63.42
 *** TIMER 15:31:07  91.04 67.23
 *** TIMER 15:31:10  94.04 70.10
 *** TIMER 15:31:14  98.04 73.91
 *** TIMER 15:31:18  102.04 77.74
 *** TIMER 15:31:20  104.04 79.61
 *** TIMER 15:31:24  108.04 83.43
 *** TIMER 15:31:28  112.04 87.29
 *** TIMER 15:31:30  114.04 89.20
 *** TIMER 15:31:34  118.04 93.01
 *** TIMER 15:31:38  122.04 96.81
 *** TIMER 15:31:40  124.04 98.69
 *** TIMER 15:31:42  126.39 100.92
 *** TIMER 15:31:46  130.04 104.45


2.3 systemd 의 timer 와 service 동시 설정


지금까지는 상위 service는 timer가 실행을 해줄 때까지 기다리고 동작을 했지만, service도 별도로 동작가능하도록 설정하여, 동시 설정하여 사용하자  

주로 이렇게 사용하는 이유는 booting 후 꼭 실행을 해야하는 경우가 될 것 같다. 


  • systemd의 timer 와 service 두개 중복 설정 
// 상위 foo.timer의 실행과 foo.service 독자적인 실행으로 중복실행방법  
$ vi /etc/systemd/system/foo.service    
or
$ vi /lib/systemd/system/foo.service  
[Unit]
Description=TEST
Requires=local-fs.target
After=local-fs.target

[Service]
Type=simple
ExecStart=/usr/bin/foo.sh

[Install]
WantedBy=multi-user.target

$ systemctl enable foo.service  // 이제 foo.service로도 동작가능 (timer가 죽어도 동작가능)  
Created symlink /etc/systemd/system/multi-user.target.wants/foo.service → /etc/systemd/system/foo.service.

$ ls -al /etc/systemd/system/multi-user.target.wants/foo.service   // 생성된 링크확인 


5/31/2020

MII Interface 기반의 ETH 과 udevd 사용 및 테스트

 1. MII interface 기반의 ETH 사용 

요즘 대체적으로 systemd-udevd 기반으로 동작

systemd-udevd   


1.1 udevadm 사용법 


systemd-udevd를 사용을 하면 기본의 udev와 다르게 udevadm으로 쉽게 제어가 가능하므로 우선 본인의 systemd-udevd 사용여부를 파악 
ps로 systemd-udevd가 동작 중인 확인 

  • udevadm 사용법 
$ udevadm -h
udevadm [--help] [--version] [--debug] COMMAND [COMMAND OPTIONS]

Send control commands or test the device manager.

Commands:
  info          Query sysfs or the udev database
  trigger       Request events from the kernel
  settle        Wait for pending udev events
  control       Control the udev daemon
  monitor       Listen to kernel and udev events
  test          Test an event run
  test-builtin  Test a built-in command 

  • udevadm 기본사용법 및 옵션 
  1.  udevadm [--debug] [--version] [--help] 
  2.  udevadm info [options] [devpath] 
  3.  udevadm trigger [options] [devpath] 
  4.  udevadm settle [options] 
  5.  udevadm control option 
  6.  udevadm monitor [options] 
  7.  udevadm test [options] devpath 
  8.  udevadm test-builtin [options] command devpath   

1.2  ETH의 분석 (MII Interface기반)


network driver는 예전처럼 /dev가 존재하지 않는 것으로 보이며, 어쩔 수 없이 /sys 파일시스템에서 확인을 해야하 하는 것으로 보인다. 

- MII Interface기반이므로 PHY 와 같이 확인 

$ SYSTEMD_LOG_LEVEL=debug udevadm info /sys/class/net/eth0 
or 
$ udevadm info /sys/class/net/eth0   // ETH0 의 세부 정보  
P: /devices/soc0/soc/2100000.aips-bus/2188000.ethernet/net/eth0     // sys filesystem path 
E: DEVPATH=/devices/soc0/soc/2100000.aips-bus/2188000.ethernet/net/eth0
E: ID_NET_DRIVER=fec
E: ID_NET_NAME_MAC=enx26e12cc4c7c6
E: ID_PATH=platform-2188000.ethernet
E: ID_PATH_TAG=platform-2188000_ethernet
E: IFINDEX=2
E: INTERFACE=eth0
E: SUBSYSTEM=net
E: SYSTEMD_ALIAS=/sys/subsystem/net/devices/eth0
E: TAGS=:systemd:
E: USEC_INITIALIZED=6203956



$ udevadm info /sys/class/net/eth0/phydev  // MII Interface PHY 정보 
P: /devices/soc0/soc/2100000.aips-bus/2188000.ethernet/mdio_bus/2188000.ethernet-1/2188000.ethernet-1:01
E: DEVPATH=/devices/soc0/soc/2100000.aips-bus/2188000.ethernet/mdio_bus/2188000.ethernet-1/2188000.ethernet-1:01
E: DEVTYPE=PHY
E: DRIVER=Generic PHY
E: MODALIAS=of:Nethernet-phyT
E: OF_COMPATIBLE_N=0
E: OF_FULLNAME=/soc/aips-bus@2100000/ethernet@2188000/mdio/ethernet-phy@1
E: OF_NAME=ethernet-phy
E: SUBSYSTEM=mdio_bus

이전의 MMC와 동일하게 분석하며 항상 uevent를 찾아 분석하자 
  • N: is for device Name in /dev (e.g /dev/ttyAMA0)
  • S: is for Symlinks to that device name in /dev  (추후 udev/rules/에서 SYMLINK)
  • P: is for device Path in /sys
  • E: is for device properties in udev

1.3 ETH0 의 속성분석 


MII Interface 의 경우, Phy와 Host 사이에 Interrupt를 사용하지 않고 Polling으로 사용하며, udev Hotplug가 미지원으로 파악 
Link 부분을 세부변화 관찰(주의, MII Phy의 Interrupt부분 재확인)  
- WOL_INT(Wake-On-Lan) Interrupt (미사용)
- INT Interrupt(Open Drain) (미사용)

  https://ahyuo79.blogspot.com/2015/02/blog-post_4.html

  • RJ45 연결시 속성값
$ udevadm info -a /sys/class/net/eth0

Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.

  looking at device '/devices/soc0/soc/2100000.aips-bus/2188000.ethernet/net/eth0':       // sys file system 기준이며, 상위 P: Node와 동일 
    KERNEL=="eth0"
    SUBSYSTEM=="net"
    DRIVER==""
    ATTR{addr_assign_type}=="0"
    ATTR{addr_len}=="6"
    ATTR{address}=="26:e1:2c:c4:c7:c6"
    ATTR{broadcast}=="ff:ff:ff:ff:ff:ff"
    ATTR{carrier}=="0"      // 현재 Not Connect 
    ATTR{carrier_changes}=="2"
    ATTR{carrier_down_count}=="1"
    ATTR{carrier_up_count}=="1"
    ATTR{dev_id}=="0x0"
    ATTR{dev_port}=="0"
    ATTR{dormant}=="0"
    ATTR{duplex}=="full"
    ATTR{flags}=="0x1003"
    ATTR{gro_flush_timeout}=="0"
    ATTR{ifalias}==""
    ATTR{ifindex}=="2"
    ATTR{iflink}=="2"
    ATTR{link_mode}=="0"
    ATTR{mtu}=="1500"
    ATTR{netdev_group}=="0"
    ATTR{operstate}=="down"   // 현재 Not Connect 
    ATTR{proto_down}=="0"
    ATTR{speed}=="100"
    ATTR{tx_queue_len}=="1000"
    ATTR{type}=="1"

  looking at parent device '/devices/soc0/soc/2100000.aips-bus/2188000.ethernet':
    KERNELS=="2188000.ethernet"
    SUBSYSTEMS=="platform"
    DRIVERS=="fec"
    ATTRS{driver_override}=="(null)"

  looking at parent device '/devices/soc0/soc/2100000.aips-bus':
    KERNELS=="2100000.aips-bus"
    SUBSYSTEMS=="platform"
    DRIVERS==""
    ATTRS{driver_override}=="(null)"

  looking at parent device '/devices/soc0/soc':
    KERNELS=="soc"
    SUBSYSTEMS=="platform"
    DRIVERS==""
    ATTRS{driver_override}=="(null)"

  looking at parent device '/devices/soc0':
    KERNELS=="soc0"
    SUBSYSTEMS=="soc"
    DRIVERS==""
    ATTRS{family}=="Freescale i.MX"
    ATTRS{revision}=="1.4"
    ATTRS{soc_id}=="i.MX6SX"    

  • RJ45 비연결할 경우 
$ udevadm info -a /sys/class/net/eth0

Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.

  looking at device '/devices/soc0/soc/2100000.aips-bus/2188000.ethernet/net/eth0':
    KERNEL=="eth0"
    SUBSYSTEM=="net"
    DRIVER==""
    ATTR{addr_assign_type}=="0"
    ATTR{addr_len}=="6"
    ATTR{address}=="26:e1:2c:c4:c7:c6"
    ATTR{broadcast}=="ff:ff:ff:ff:ff:ff"
    ATTR{carrier}=="1"               // 현재 Connect(up) 상태 
    ATTR{carrier_changes}=="3"      // 현재 Connect(up/down) 상태 변환 Count
    ATTR{carrier_down_count}=="1"  // down count
    ATTR{carrier_up_count}=="2"    // up count 
    ATTR{dev_id}=="0x0"
    ATTR{dev_port}=="0"
    ATTR{dormant}=="0"
    ATTR{duplex}=="full"
    ATTR{flags}=="0x1003"
    ATTR{gro_flush_timeout}=="0"
    ATTR{ifalias}==""
    ATTR{ifindex}=="2"
    ATTR{iflink}=="2"
    ATTR{link_mode}=="0"
    ATTR{mtu}=="1500"
    ATTR{netdev_group}=="0"
    ATTR{operstate}=="up"  // 현재 Connect 상태 
    ATTR{proto_down}=="0"
    ATTR{speed}=="100"
    ATTR{tx_queue_len}=="1000"
    ATTR{type}=="1"

  looking at parent device '/devices/soc0/soc/2100000.aips-bus/2188000.ethernet':
    KERNELS=="2188000.ethernet"
    SUBSYSTEMS=="platform"
    DRIVERS=="fec"
    ATTRS{driver_override}=="(null)"

  looking at parent device '/devices/soc0/soc/2100000.aips-bus':
    KERNELS=="2100000.aips-bus"
    SUBSYSTEMS=="platform"
    DRIVERS==""
    ATTRS{driver_override}=="(null)"

  looking at parent device '/devices/soc0/soc':
    KERNELS=="soc"
    SUBSYSTEMS=="platform"
    DRIVERS==""
    ATTRS{driver_override}=="(null)"

  looking at parent device '/devices/soc0':
    KERNELS=="soc0"
    SUBSYSTEMS=="soc"
    DRIVERS==""
    ATTRS{family}=="Freescale i.MX"
    ATTRS{revision}=="1.4"
    ATTRS{soc_id}=="i.MX6SX"

  • sys filesystem에서 Ethernet Link 확인 
fec 2188000.ethernet eth0: Link is Up - 100Mbps/Full - flow control rx/tx
$ cat /sys/class/net/eth0/carrier        // sys filesystem의 상태 확인 
1

fec 2188000.ethernet eth0: Link is Down
$ cat /sys/class/net/eth0/carrier        // sys filesystem 의 상태확인 
0    

$ networkctl list  // networkctl에서도 감지 
2 eth0         ether    routable    configured

$ networkctl list  // networkctl에서도 감지 
2 eth0         ether    no-carrier    configured

$ networkctl status eth0


/etc/systemd/network/eth0.network에서 DefaultRouteOnDevice=yes 설정하여 상위에서 routable 가능 


1.4 udevadm 으로 uevent 감시 


세부적으로 SUBSYSTEM 값이 "net"이므로, 이를 기반으로 세부적으로 감시했으나, ETH0의 변화가 없음 

$ udevadm -d monitor -p -k -u --subsystem-match=net   // eth0 Hotplug 포인트를 못찾음
calling: monitor
monitor will print the received events for:
UDEV - the event which udev sends out after rule processing
KERNEL - the kernel uevent

fec 2188000.ethernet eth0: Link is Down
fec 2188000.ethernet eth0: Link is Up - 100Mbps/Full - flow control rx/tx



KERNEL[44684.453030] remove   /devices/virtual/net/ppp0 (net)     // 오직 ppp만 찾음 
ACTION=remove
DEVPATH=/devices/virtual/net/ppp0
DEVTYPE=ppp
IFINDEX=9
INTERFACE=ppp0
SEQNUM=2191
SUBSYSTEM=net

UDEV  [44684.474359] remove   /devices/virtual/net/ppp0 (net)
ACTION=remove
DEVPATH=/devices/virtual/net/ppp0
DEVTYPE=ppp
IFINDEX=9
INTERFACE=ppp0
SEQNUM=2191
SUBSYSTEM=net
SYSTEMD_ALIAS=/sys/subsystem/net/devices/ppp0
TAGS=:systemd:
USEC_INITIALIZED=26876345

KERNEL[44690.852770] add      /devices/virtual/net/ppp0 (net)
ACTION=add
DEVPATH=/devices/virtual/net/ppp0
DEVTYPE=ppp
IFINDEX=10
INTERFACE=ppp0
SEQNUM=2192
SUBSYSTEM=net

UDEV  [44690.883719] add      /devices/virtual/net/ppp0 (net)
ACTION=add
DEVPATH=/devices/virtual/net/ppp0
DEVTYPE=ppp
IFINDEX=10
INTERFACE=ppp0
SEQNUM=2192
SUBSYSTEM=net
SYSTEMD_ALIAS=/sys/subsystem/net/devices/ppp0
TAGS=:systemd:
USEC_INITIALIZED=44690865786

$ udevadm monitor /sys/class/net/eth0
monitor will print the received events for:
UDEV - the event which udev sends out after rule processing
KERNEL - the kernel uevent

fec 2188000.ethernet eth0: Link is Up - 100Mbps/Full - flow control rx/tx
fec 2188000.ethernet eth0: Link is Down
fec 2188000.ethernet eth0: Link is Up - 100Mbps/Full - flow control rx/tx

2. udev Rule 설정 


아래와 같이 넣어 동작확인을 했지만, 동작되지 않으며 세부감시를 위해서 udev monitor에서 감시했지만, 감시가 안됨 (udev로 control 이 안됨)

$ vi /etc/udev/rules.d/30-eth.rules  // 동작테스트 (실패)
KERNEL=="eth0", SUBSYSTEM=="net", ATTR{carrier}=="0", RUN+="echo hello world" 

$ vi /etc/udev/rules.d/30-eth.rules  // 동작테스트 (실패)
ACTION=="add" KERNEL=="eth0", SUBSYSTEM=="net", ATTR{carrier}=="1", RUN+="echo 11111111" 
ACTION=="remove" KERNEL=="eth0", SUBSYSTEM=="net", ATTR{carrier}=="0", RUN+="echo 22222222" 

// 상위 두개 다 동작이 안됨  udev로 보고가 안됨 MII Phy의 연결된 Interrupt가 udev와 같이 동작되지 않는 것으로 추측
// ATTR{operstate} 로 해도 동일 


/sys/class/net/eth0/operstate  Application C언어 예제 
(Kernel의 rtnetlink.h 사용)
  https://stackoverflow.com/questions/26672414/inotify-add-watch-fails-on-sys-class-net-eth0-operstate#26674239

GPIO의 경우 /sys/class/gpio 로 fopen or open으로 직접 control 하자 
  https://infoarts.tistory.com/21


udev write rules 관련사항
  http://www.reactivated.net/writing_udev_rules.html

udev network rules 관련사항
  https://alwaystinkering.wordpress.com/2016/05/15/udev-network-interface-renaming-with-no-reboot/

3. udev TEST 


$ udevadm control --reload-rules  // 상위에서 만든 Rules 적용했지만 Trigger에서 미동작함 
$ udevadm test /sys/class/net/eth0  //TEST를 진행을 해보면 쉽게 우선순위를 확인가능
calling: test
version 239
This program is for debugging only, it does not run any program
specified by a RUN key. It may show incorrect results, because
some values may be different, or not available at a simulation run.

Load module index
Skipping empty file: /etc/systemd/network/99-default.link
Created link configuration context.
Reading rules file: /etc/udev/rules.d/10-imx.rules
Reading rules file: /etc/udev/rules.d/30-mmc.rules
Reading rules file: /etc/udev/rules.d/40-eth.rules
Reading rules file: /lib/udev/rules.d/50-firmware.rules
Reading rules file: /etc/udev/rules.d/50-ttyACM.rules
Reading rules file: /lib/udev/rules.d/50-udev-default.rules
Reading rules file: /lib/udev/rules.d/60-block.rules
Reading rules file: /lib/udev/rules.d/60-cdrom_id.rules
Reading rules file: /lib/udev/rules.d/60-drm.rules
Reading rules file: /lib/udev/rules.d/60-evdev.rules
Reading rules file: /lib/udev/rules.d/60-input-id.rules
Reading rules file: /lib/udev/rules.d/60-persistent-alsa.rules
Reading rules file: /lib/udev/rules.d/60-persistent-input.rules
Reading rules file: /lib/udev/rules.d/60-persistent-storage-tape.rules
Reading rules file: /lib/udev/rules.d/60-persistent-storage.rules
Reading rules file: /lib/udev/rules.d/60-persistent-v4l.rules
Reading rules file: /lib/udev/rules.d/60-sensor.rules
Reading rules file: /lib/udev/rules.d/60-serial.rules
Reading rules file: /lib/udev/rules.d/64-btrfs.rules
Reading rules file: /lib/udev/rules.d/70-joystick.rules
Reading rules file: /lib/udev/rules.d/70-mouse.rules
Reading rules file: /lib/udev/rules.d/70-power-switch.rules
Reading rules file: /lib/udev/rules.d/70-touchpad.rules
Reading rules file: /lib/udev/rules.d/70-uaccess.rules
Reading rules file: /lib/udev/rules.d/71-seat.rules
Reading rules file: /lib/udev/rules.d/73-seat-late.rules
Reading rules file: /lib/udev/rules.d/75-net-description.rules
Reading rules file: /lib/udev/rules.d/75-probe_mtd.rules
Reading rules file: /lib/udev/rules.d/78-sound-card.rules
Reading rules file: /lib/udev/rules.d/80-drivers.rules
Reading rules file: /lib/udev/rules.d/80-net-setup-link.rules
Reading rules file: /lib/udev/rules.d/90-alsa-restore.rules
Reading rules file: /lib/udev/rules.d/90-vconsole.rules
Reading rules file: /lib/udev/rules.d/97-hid2hci.rules
Reading rules file: /lib/udev/rules.d/99-systemd.rules
Reading rules file: /etc/udev/rules.d/touchscreen.rules
rules contain 24576 bytes tokens (2048 * 12 bytes), 11301 bytes strings
1619 strings (19672 bytes), 1047 de-duplicated (8944 bytes), 573 trie nodes used
IMPORT builtin 'net_id' /lib/udev/rules.d/75-net-description.rules:6
IMPORT builtin 'path_id' /lib/udev/rules.d/80-net-setup-link.rules:5
IMPORT builtin 'net_setup_link' /lib/udev/rules.d/80-net-setup-link.rules:9
No matching link configuration found.
RUN '/lib/systemd/systemd-sysctl --prefix=/net/ipv4/conf/$name --prefix=/net/ipv4/neigh/$name --prefix=/net/ipv6/conf/$name --prefix=/net/ipv6/neigh/$name' /lib/udev/rules.d/99-systemd.rules:60
ACTION=add
DEVPATH=/devices/soc0/soc/2100000.aips-bus/2188000.ethernet/net/eth0
ID_NET_DRIVER=fec
ID_NET_NAME_MAC=enx26e12cc4c7c6
ID_PATH=platform-2188000.ethernet
ID_PATH_TAG=platform-2188000_ethernet
IFINDEX=2
INTERFACE=eth0
SUBSYSTEM=net
SYSTEMD_ALIAS=/sys/subsystem/net/devices/eth0
TAGS=:systemd:
USEC_INITIALIZED=6371280
run: '/lib/systemd/systemd-sysctl --prefix=/net/ipv4/conf/eth0 --prefix=/net/ipv4/neigh/eth0 --prefix=/net/ipv6/conf/eth0 --prefix=/net/ipv6/neigh/eth0'
Unload module index
Unloaded link configuration context.




$ udevadm trigger -c change -a carrier=0 /sys/class/net/eth0   // 변경이 안됨 
$ udevadm trigger -c change -a carrier=1 /sys/class/net/eth0     // 변경이 안됨


4/20/2020

firewall 설정 및 Service 등록

1. firewall 기본이해  

Linux의 firewall 기능은 기본적으로 iptables 와 firewalld가 존재하며, 기존부터 사용하던 것이 iptables 이라고 한다.
기존의 RTOS를 제외하고 Linux의 경우 firewall 기능을 거의 사용해본적이 없어 관련내용을 새롭게 알게되었다.

  • Linux에서 지원되는 Firewall Package
  1. firewalld:  GUI Interface를 제공하며, Kernel Netffilter 부분이용
  2. iptables: GUI Interface를 미제공하며, Kernel Netfilter 부분이용

iptables은 쉽게 command 형식으로 동작가능하며, firewalld는 iptables과 기능이 비슷한 nftables 기반으로 동작되어진다고 한다.
세부적으로 잘 모르겠지만, 간단히 비교하자면, firewalld는 편이성을 목적을 둔 것 같으며, iptables은 이전부터 사용하던 command 방식인것 같다.

Firewalld 관련사항
  https://en.wikipedia.org/wiki/Firewalld

1.1 Netfilter 의 기능 

firewalld를 사용하던 iptables을 사용하던 Kernel Netfilter 설정은 필수이며 이부분은 어쩔수 없다.
두 기능을 제대로 사용하고자 한다면 Kernel의 설정은 필수이지만, iptables을 사용하는지 nftables을 사용하는지에 따라 Kernel 설정은 달라지는 것 같다.

Netfilter 관련사항
  https://en.wikipedia.org/wiki/Netfilter

Firewalld 사용하는 nftables 기능
  https://wiki.gentoo.org/wiki/Nftables

Netfilter 관련 Project 정보
  https://netfilter.org/

1.2 Kernel 의 Netfilter 설정

현재 nftables 대신에 iptables을 사용할 것이며, 가급적 필요없는 기능은 빼도록 하자.
Kernel 옵션과 iptables의 설명서의 세부옵션을 자세히 보면 설정은 이해가 대충간다.
nftables 관련부분은 설정하지 않았지만, 유사할 것이라고 생각이 든다.

  • nftables의 kernel 기본설정 
[*] Networking support  --->
    Networking options  --->
        [*] Network packet filtering framework (Netfilter)  --->
            Core Netfilter Configuration  --->
                 Netfilter nf_tables support
                   Netfilter nf_tables conntrack module
                   Netfilter nf_tables counter module
                   Netfilter nf_tables log module
                   Netfilter nf_tables limit module
                   Netfilter nf_tables masquerade support
                   Netfilter nf_tables nat module
            IP: Netfilter Configuration  --->
                 IPv4 nf_tables support
                   IPv4 nf_tables route chain support
                 IPv4 packet rejection
                 IPv4 NAT
                   IPv4 nf_tables nat chain support
                   IPv4 masquerade support
                   IPv4 masquerading support for nf_tables

  https://wiki.gentoo.org/wiki/Nftables
  https://wiki.nftables.org/wiki-nftables/index.php/Building_and_installing_nftables_from_sources

NAT 설정시 상위 Kernel 설정필수

  • iptables kernel 기본설정 
[*] Networking support  --->                                          [CONFIG_NET]
      Networking Options  --->
        [*] Network packet filtering framework (Netfilter) --->       [CONFIG_NETFILTER]
          [*] Advanced netfilter configuration                        [CONFIG_NETFILTER_ADVANCED]   // iptables의 세부옵션까지 설정가능 (현재 불필요)
          Core Netfilter Configuration --->
            <*/M> Netfilter connection tracking support               [CONFIG_NF_CONNTRACK]  // iptables의 옵션의 conntrack 기능 설정 
            <*/M> Netfilter Xtables support (required for ip_tables)  [CONFIG_NETFILTER_XTABLES]
            <*/M> LOG target support                                  [CONFIG_NETFILTER_XT_TARGET_LOG]  // iptables의 기능 중 LOG로 남길수 있는 기능 
          IP: Netfilter Configuration --->
            <*/M> IP tables support (required for filtering/masq/NAT) [CONFIG_IP_NF_IPTABLES]

설정관련사항 및 Download
  http://www.linuxfromscratch.org/blfs/view/svn/postlfs/iptables.html


  • iptables의 client (현재 이 옵션에 맞춰 설정)
[*] Networking support  --->
    Networking options  --->
        ...
        [*] TCP/IP networking
        [ ]   IP: multicasting
        [ ]   IP: advanced router
        [ ]   IP: kernel level autoconfiguration
        < >   IP: tunneling
        < >   IP: GRE demultiplexer
        [ ]   IP: TCP syncookie support
        < >   Virtual (secure) IP: tunneling
        < >   IP: AH transformation
        < >   IP: ESP transformation
        < >   IP: IPComp transformation
        <*>   IP: IPsec transport mode
        <*>   IP: IPsec tunnel mode
        < >   IP: IPsec BEET mode
        < >   Large Receive Offload (ipv4/tcp)
        <*>   INET: socket monitoring interface
        < >     UDP: socket monitoring interface
        [ ]   TCP: advanced congestion control  ----
        [ ]   TCP: MD5 Signature Option support (RFC2385)
        <*>   The IPv6 protocol  --->
        [ ] Security Marking
        [ ] Timestamping in PHY devices
        [*] Network packet filtering framework (Netfilter)  --->
            --- Network packet filtering framework (Netfilter)
            [ ]   Network packet filtering debugging
            [ ]   Advanced netfilter configuration
                  Core Netfilter Configuration  --->
                       Netfilter LOG over NFNETLINK interface
                      <*> Netfilter connection tracking support
                      [ ]   Supply CT list in procfs (OBSOLETE)
                      < >   FTP protocol support
                      < >   IRC protocol support
                      < >   NetBIOS name service protocol support
                      < >   SIP protocol support
                      < >   Connection tracking netlink interface
                      < > Netfilter nf_tables support
                      -*- Netfilter Xtables support (required for ip_tables)
                            *** Xtables combined modules ***
                      < >   nfmark target and match support
                            *** Xtables targets ***
                      < >   LOG target support
                      < >   "NFLOG" target support
                      < >   "TCPMSS" target support
                            *** Xtables matches ***
                      <*>   "conntrack" connection tracking match support   // iptable 의 conntrack option 기능사용
                      < >   IPsec "policy" match support
                      < >   "state" match support
            < >   IP set support  ----
            < >   IP virtual server support  ----
                  IP: Netfilter Configuration  --->
                      <*> IPv4 connection tracking support (required for NAT)
                      <*> IP tables support (required for filtering/masq/NAT)
                      <*>   Packet filtering
                      <*>     REJECT target support
                      < >   ULOG target support (obsolete)
                      < >   IPv4 NAT
                      < >   Packet mangling
                      < >   raw table support (required for NOTRACK/TRACE)
                  IPv6: Netfilter Configuration  --->
                      <*> IPv6 connection tracking support
                      <*> IP6 tables support (required for filtering)
                      < >   "ipv6header" IPv6 Extension Headers Match
                      <*>   Packet filtering
                      <*>     REJECT target support
                      < >   Packet mangling
                      < >   raw table support (required for TRACE)


  • iptables의 router 기준옵션
[*] Networking support  --->
    Networking options  --->
        [*] TCP/IP networking
        [*]   IP: multicasting
        [*]   IP: advanced router
        ...
        [*]   IP: ARP daemon support
        [*]   IP: TCP syncookie support
        <m>   IP: AH transformation
        <m>   IP: ESP transformation
        <m>   IP: IPComp transformation
        <m>   IP: IPsec transport mode
        <m>   IP: IPsec tunnel mode
        <m>   IP: IPsec BEET mode
        <*>   Large Receive Offload (ipv4/tcp)
        <*>   INET: socket monitoring interface
        <m>     UDP: socket monitoring interface
        [ ]   TCP: advanced congestion control  --->
        ...
           The IPv6 protocol  ---&gt;
        ...
        [*] Network packet filtering framework (Netfilter)  --->
            [*]   Advanced netfilter configuration      // 좀 더 많은 iptable 옵션설정가능 
            Core Netfilter Configuration  --->
                <m>   "addrtype" address type match support  // iptable 명령어의 세부옵션
                <m>   "comment" match support                // iptable 명령어의 세부옵션
                <m>   "hl" hoplimit/TTL match support        // iptable 명령어의 세부옵션
                <m>   "limit" match support                  // iptable 명령어의 세부옵션
                <m>   "multiport" Multiple port match support // iptable 명령어의 세부옵션
                <m>   "recent" match support                  // iptable 명령어의 세부옵션

상위설정관련내용
  https://wiki.gentoo.org/wiki/Iptables


2. iptables 와 ip6tables설정 

ipv4 는 iptables 이며, ipv6는 당연히 ip6tables로 쉽게 설정가능하다.

  • iptables의 기본사용법
iptables [-t table] {-A|-D} chain rule-specification
iptables [-t table] -I chain [rulenum] rule-specification
iptables [-t table] -R chain rulenum rule-specification
iptables [-t table] -D chain rulenum
iptables [-t table] -S [chain [rulenum]]
iptables [-t table] {-F|-L|-Z} [chain [rulenum]] [options...]
iptables [-t table] -N chain
iptables [-t table] -X [chain]
iptables [-t table] -P chain target          
iptables [-t table] -E old-chain-name new-chain-name

  https://linux.die.net/man/8/iptables
  https://linux.die.net/man/8/ip6tables

  • chain 
  1. INPUT: Host로 들어오는 방향관리
  2. OUTPUT: Host에서 나가는 방향관리
  3. FORWARD: Host에서 Forward해주는 부분관리 
  4. User-defined: -N Command를 이용하여 새로운 Chain 생성가능 

  • target
  1. ACCEPT : Packet의 허용
  2. DROP : Packet을 버림
  3. User-define Chain: 
  4. LOG  ( KERNCONFIG의 상위 LOG설정필요), syslog에 설정 

  • table  (미사용)
  1. filter  (KERNEL CONFIG 의 CONFIG_IP_NF_FILTER  설정필요) 
  2. nat     (KERNEL CONFIG 의 CONFIG_IP_NF_NAT   설정필요)    (option)
  3. mangle  (KERNEL CONFIG 의 CONFIG_IP_NF_MANGLE 설정필요)   (option)
  4. raw     (KERNEL CONFIG 의 CONFIG_IP_NF_RAW 설정필요)   (option)

iptable 기본사용법
  https://brownbears.tistory.com/151
  https://linux.die.net/man/8/iptables


2.1 iptable 기본 사용법 

  • iptable 현재 설정상태 확인
policy가 모두 ACCEPT로 되어있어, 모든 Connection 허락하며 별도로 설정된 설정이 없음

$ iptables -L     // 기본 설정확인 확인  Chain은 기본으로 3개 
or
$ iptables -L  -n  

Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

$ iptables -nvL --line-numbers  //기본설정확인 및 세부사항확인 
Chain INPUT (policy ACCEPT 3 packets, 96 bytes)
num   pkts bytes target     prot opt in     out     source               destination

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination


  • iptable policy 설정 
기본 정책은 모든 INPUT/ OUTPUT/FORWARD를 전부 막고, ACCEPT 해줄 것을 이후에 별도로 설정하면 됨

$ iptables -P INPUT   DROP
$ iptables -P FORWARD DROP
$ iptables -P OUTPUT  DROP

기본 정책은 모든 INPUT/ FORWARD만 만 막고 OUTPUT은 허용

$ iptables -P INPUT   DROP
$ iptables -P FORWARD DROP
$ iptables -P OUTPUT  ACCEPT 

모두 허용

$ iptables -P INPUT   ACCEPT 
$ iptables -P FORWARD ACCEPT 
$ iptables -P OUTPUT  ACCEPT 


  • local device 허용
$ iptables -A INPUT  -i lo -j ACCEPT
$ iptables -A OUTPUT -o lo -j ACCEPT


  • NAT의 기능 
iptable을 이용하여 NAT기능도 사용가능하며, 상위 커널설정은 반드시 필요 


기본으로 Kernel 에서 Netfilter 부분설정 
# 상위그림 처럼 막음 Disabled by default!  
$  echo "1" > /proc/sys/net/ipv4/ip_forward


$ iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE     // eth1 NAT 설정 

NAT 및 포트포워딩 관련세부사항 아래 참조
  https://www.karlrupp.net/en/computer/nat_tutorial
  http://www.netfilter.org/projects/iptables/index.html

  • Incoming/outcoming 허용
policy를 drop으로 되어있을 경우 아래와 같이 Server의 특정 Port를 연결을 해주어 동작하도록 한다.
보통 Server는 Listeing port 와 communication port가 다르므로 관련부분을 설정

$ iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
$ iptables -A OUTPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

iptables 일반적인 command
  https://www.digitalocean.com/community/tutorials/iptables-essentials-common-firewall-rules-and-commands


iptables 사용법 참조
  https://linux.die.net/man/8/iptables
  https://www.thegeekstuff.com/2011/03/iptables-inbound-and-outbound-rules/
  https://idchowto.com/?p=38658
  https://ko.wikipedia.org/wiki/Iptables
  https://wiki.archlinux.org/index.php/Iptables
  https://linuxstory1.tistory.com/entry/iptables-%EA%B8%B0%EB%B3%B8-%EB%AA%85%EB%A0%B9%EC%96%B4-%EB%B0%8F-%EC%98%B5%EC%85%98-%EB%AA%85%EB%A0%B9%EC%96%B4
  https://pydole.tistory.com/entry/iptables-%EC%B0%A8%EB%8B%A8-%EB%A1%9C%EA%B7%B8-%EB%AA%A8%EB%8B%88%ED%84%B0%EB%A7%81-1-%EB%A1%9C%EA%B7%B8-%EB%82%A8%EA%B8%B0%EA%B8%B0


2.2 iptable 용 systemd service 설정 

  • iptable 설정 script 
service 를 위해서 사용할 iptable용 Shell Script 작성 

$ cat /usr/bin/firewall.sh
#!/bin/bash
# Configure iptables firewall

# Limit PATH
PATH="/sbin:/usr/sbin:/bin:/usr/bin"

firewall_start() {

  # interface lo (loopback)
  # Accept everything on loopback
  iptables -A INPUT  -i lo -j ACCEPT
  iptables -A OUTPUT -o lo -j ACCEPT

  #
  # default setting 
  #
  iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
  iptables -A OUTPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

  #
  # ping 
  #
  iptables -A INPUT -p icmp -j ACCEPT
  iptables -A OUTPUT -p icmp -j ACCEPT

  #
  # SSH Server TCP Destination Port 22 (dport)
  # 
  iptables -A INPUT  -p tcp --dport 22 -j ACCEPT  

  #
  # SSH Client TCP Destination Port 22 
  # 
  iptables -A OUTPUT -p tcp --dport 22  -j ACCEPT

  #
  # Default Policy 
  #
  iptables -P INPUT   DROP
  iptables -P FORWARD DROP
  iptables -P OUTPUT  ACCEPT
  #iptables -P OUTPUT  DROP
}

firewall_stop() {
  # iptable flush setting
  iptables -F
  # iptable delete all of chains
  iptables -X
  # iptable default policy setting 
  iptables -P INPUT   ACCEPT
  iptables -P FORWARD ACCEPT
  iptables -P OUTPUT  ACCEPT
}

# execute action
case "$1" in
  start|restart)
    echo "Start firewall, your setting"
    firewall_stop
    firewall_start
    ;;
  stop)
    echo "Stop firewall, default setting"
    firewall_stop
    ;;
esac


  • systemd service file 설정

$ vi /lib/systemd/system/firewall.service
or 
$ vi /etc/systemd/system/firewall.service     // etc로 추천 

[Unit]
Description=iptables firewall service
After=network.target

[Service]
Type=oneshot
ExecStart=/usr/bin/firewall.sh start
RemainAfterExit=true
ExecStop=/usr/bin/firewall.sh stop
StandardOutput=journal

## multi-user.target 
[Install]
WantedBy=multi-user.target

$ systemctl status firewall.service

$ systemctl enable firewall.service     // enable 시 아래의 주소로 link 생성되며 동작 

$ ls /etc/systemd/system/multi-user.target.wants/firewall.service  // 상위 install 

$ systemctl start firewall.service  
or
$ init 6  // reboot

iptables의 shellscript 관련예제
    https://blog.sleeplessbeastie.eu/2018/10/01/how-to-make-iptables-configuration-persistent-using-systemd/

2/13/2020

SD/MMC 와 udev 재분석 과 Rule 생성

1.  SD/MMC Spec 및 기본확인법 

MMC 혹은 SDCard 관련 Spec을 다시 확인하고자 한다면 아래의 사이트에서 확인




  • MMC(SDCARD) 관련 Spec
  1. Part 1. Physical Layer Simplified Specification 
  2. Part A2. SD Host Controller Simplified Specification
  3. Part E1. SDIO Simplified Specification 
  4. Part E7. Wireless LAN Simplified Addendum
  5. 이외 
대부분의 기본적인 내용은 Part1. Physical Layer Simplified Specification 을 보면 구조 및 기본동작이 이해가가능하며,
UHS-II 관련부분이나 다른 SD 확장 API를 본다면 해당 문서를 참조

SD/MMC 관련 Spec Download
  https://www.sdcard.org/downloads/pls/

1.1 SD/MMC 정보확인 

SD/MMC 기본 Register


  • SD/MMC Register 확인 
$ find /sys -name cid  // CID Register 제조사 및 제품정보 파악가능 (Spec참조)
/sys/devices/soc0/soc/2100000.aips-bus/219c000.usdhc/mmc_host/mmc3/mmc3:0001/cid     //eMMC
/sys/devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234/cid     //SDCard 

$ find /sys -name csd //CSD를 통해 MMC의 Spec 및 성능파악 (Spec참조)
/sys/devices/soc0/soc/2100000.aips-bus/219c000.usdhc/mmc_host/mmc3/mmc3:0001/csd //eMMC
/sys/devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234/csd //SDCard 

$ find /sys -name scr // SDCard에 설정된 기본정보 (Databit,SDCard 종류) 확인가능 (Spec)
/sys/devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234/scr  //SDCard 

$ find /sys -name dsr or rca or ocr //기타정보들 
  • SD/MMC 기본정보파악 
$ find /sys -name ios // 쉽게 MMC의 정보파악 
/sys/kernel/debug/mmc3/ios  //eMMC
/sys/kernel/debug/mmc2/ios  //SDCard

$ cat /sys/kernel/debug/mmc3/ios  //eMMC 8bit
clock:          198000000 Hz
actual clock:   198000000 Hz
vdd:            21 (3.3 ~ 3.4 V)
bus mode:       2 (push-pull)
chip select:    0 (don't care)
power mode:     2 (on)
bus width:      3 (8 bits)
timing spec:    9 (mmc HS200)
signal voltage: 1 (1.80 V)
driver type:    0 (driver type B)

$ cat /sys/kernel/debug/mmc2/ios  //SD Card 4bit
clock:          50000000 Hz
actual clock:   49500000 Hz
vdd:            18 (3.0 ~ 3.1 V)
bus mode:       2 (push-pull)
chip select:    0 (don't care)
power mode:     2 (on)
bus width:      2 (4 bits)
timing spec:    2 (sd high-speed)
signal voltage: 0 (3.30 V)
driver type:    0 (driver type B) 
  • SD Card의 경우 CD(Card Detection)/WP(Write Protection) 
$ cat /proc/interrupts | egrep "(mmc|cd)" // SDCard는 Hotplug를 위해 CD필요 
 63:        676       GPC  24 Level     mmc2  //SDCard
 64:       9336       GPC  25 Level     mmc3  //eMMC 
 78:          0       GPC   6 Edge      2224000.lcdif
126:          3  gpio-mxc  10 Edge      2198000.usdhc cd  //SDCard Card Detection (Hotplug)

// SD Card Detection의 GPIO 및 Trigger 및 IRQ 확인 
$ cat /sys/kernel/debug/gpio | grep cd  
 gpio-42  (                    |cd                  ) in  hi IRQ 
SD Card의 경우 CD 와 WP Pin을 GPIO로 연결하여 사용가능하며, 주로 CD 사용할 경우 Hotplug가능. WP 미사용

eMMC/SD Card 관련참고사항
  https://developer.toradex.com/knowledge-base/sd-mmc-card-(linux)

1.2 SD/MMC의 Kernel 관련정보 

  • i.MX Kernel Config
  1. MMC/SD/SDIO (CONFIG_MMC)
  2. MMC block (CONFIG_MMC_BLOCK)
  3. Secure Digital Host Controller Interface support (CONFIG_MMC_SDHCI)
  4. SDHCI support on the platform-specific bus (CONFIG_MMC_SDHCI_PLTFM)
  5. SDHCI platform support for the NXP eSDHC i.MX controller (CONFIG_MMC_SDHCI_ESDHC_IMX)

  • Kernel source의 drivers/mmc/host/  
  1. sdhci.c standard stack code
  2. sdhci-pltfm.c sdhci platform layer
  3. sdhci-esdhc.c uSDHC driver
  4. sdhci-esdhc-imx.c uSDHC driver header file

세부사항은 아래사이트 참고

  • i.MX 관련설정 (출처) 
MMC/SDCard/SDIO Kernel 설정을 비롯하여Device Tree 설정정보를제공
  https://www.digi.com/resources/documentation/digidocs/90001546/reference/bsp/cc6/r_mmc-sd-sdio.htm


  • MMC/SD Device Driver 세부분석 
새로 SD/MMC를 분석할 필요는 없는 것 같아 아래사이트를 참조하여 이해만하고 넘어감
  http://egloos.zum.com/furmuwon/v/11167927

  • SDCard 관련부분 Uboot 및 Kernel 설정 (Sitara/i.MX)
아래사이트에서 쉽게 설정이 가능하도록 제공
  https://www.digikey.com/eewiki/pages/viewpage.action?pageId=35193201#BeagleBoneBlack-uEnv.txtbasedbootscript
  https://www.digikey.com/eewiki/display/linuxonarm/i.MX6+SABRE+Lite
  https://developer.toradex.com/knowledge-base/sd-mmc-card-(linux)


1.3  Kernel의 Netlink uevent 와 udev 통신 

Kernel은 udevNETLINK_KOBJECT_UEVENT로 통신을 하고 있으며, 이곳에 add_uevent_var의 환경설정값을 추가하여 통신을 진행한다.
Kernel은 이외에도 다른 NETLINK도 사용하니 이것만 사용한다고 착각하지말자.

  • udev의 NETLINK_KOBJECT_UEVENT
ue_sk->sk = netlink_kernel_create(net, NETLINK_KOBJECT_UEVENT, &cfg);
user에서 socket으로 protocol을 NETLINK_KOBJECT_UEVENT로 설정 
  https://elixir.bootlin.com/linux/v4.20.4/source/lib/kobject_uevent.c#L751

  • SD/MMC 관련소스
아래부분은 SD/MMC에서 공통으로사용되는 부분으로 필요할때만 보고, Chip Vendor관련부분은 상위에서 처럼 관련부분은 별도로 보자.
  https://elixir.bootlin.com/linux/v4.17.19/source/drivers/mmc/core
  https://elixir.bootlin.com/linux/v4.17.19/source/drivers/mmc/core/mmc.c

  • kobject_uevent->kobject_uevent_env
보통 uevent는 아래와 같이 동작을 하며, 아래와 같이 각각의 환경변수값을 uevent와 함께보내면, udevd은 이를 받아 database로 기록하여 사용한다고한다.
  1. retval = add_uevent_var(env, "ACTION=%s", action_string);
  2. retval = add_uevent_var(env, "DEVPATH=%s", devpath);
  3. retval = add_uevent_var(env, "SUBSYSTEM=%s", subsystem);
  4. retval = add_uevent_var(env, "%s", envp_ext[i]);  // 상위 NULL 이지만 sys에서 설정가능
  5. retval = add_uevent_var(env, "SEQNUM=%llu", (unsigned long long)++uevent_seqnum);
  6. 기타 값 
  https://elixir.bootlin.com/linux/v4.20.4/source/lib/kobject_uevent.c#L454


  • kobject_synth_uevent 관련함수
  https://elixir.bootlin.com/linux/v4.20.4/source/lib/kobject_uevent.c#L192


  • kobject_uevent_env 의 확장값을 넣어 전송
  1. LEASE=1    :  상위 3번의 envp_ext[i] 값 설정 
  2. HOTPLUG=1 : 상위 3번의 envp_ext[i] 값 설정 
  https://elixir.bootlin.com/linux/v4.20.4/source/drivers/gpu/drm/drm_sysfs.c#L322
  https://elixir.bootlin.com/linux/v4.20.4/source/drivers/gpu/drm/drm_sysfs.c#L304


  • kobject 와 sysfiletem을 세부적으로 분석 (반드시 참고)
*** 관련내용을 찾다가 아래사이트에서 자세히 분석해줘서 이해하기가 더 쉬움 (감사할 따름)
  http://jake.dothome.co.kr/kobject/


  • device driver의 attribute의 구성을 쉽게 이해가능 (sys file system 구성)
attribute는 sys filesystem의 구성이기때문에 반드시 사용법 숙지하며, 이외에도 가끔 소스를 보면 다른 것도 존재하는 것 같은데, 그 부분은 추후 추가
  1. device_attribute
  2. bus_attribute
  3. class_attribute
  4. driver_attribute

오래전의 linux kernel과 attribute설정방법은 조금 다르지만 거의 비슷함
  http://jake.dothome.co.kr/device-driver-1/

2. udev 분석 및 테스트진행 

현재 udevadm command로 통합이되어 관련명령어를 모두 사용이 가능하며, 이를 이용하여 udev의 정보 및 테스트도 진행이 가능하다.

$ udevadm -h
udevadm [--help] [--version] [--debug] COMMAND [COMMAND OPTIONS]

Send control commands or test the device manager.

Commands:
  info          Query sysfs or the udev database  //
  trigger       Request events from the kernel
  settle        Wait for pending udev events
  control       Control the udev daemon
  monitor       Listen to kernel and udev events
  test          Test an event run
  test-builtin  Test a built-in command


  http://fibrevillage.com/sysadmin/93-udevadm-command-examples

2.1 udevadm info 기본분석방법 

udevadm info를 이용하여 udev의 database 정보와 sysfs 정보를 확인가능하므로, 이를 이용하여 udev 분석이 쉬어진다.

$ udevadm info  -h
udevadm info [OPTIONS] [DEVPATH|FILE]

Query sysfs or the udev database.

  -h --help                   Print this message
  -V --version                Print version of the program
  -q --query=TYPE             Query device information:
       name                     Name of device node
       symlink                 Pointing to node
       path                     sysfs device path
       property                The device properties
       all                      All values
  -p --path=SYSPATH           sysfs device path used for query or attribute walk
  -n --name=NAME              Node or symlink name used for query or attribute walk
  -r --root                   Prepend dev directory to path names
  -a --attribute-walk         Print all key matches walking along the chain
                              of parent devices
  -d --device-id-of-file=FILE Print major:minor of device containing this file
  -x --export                 Export key/value pairs
  -P --export-prefix          Export the key name with a prefix
  -e --export-db              Export the content of the udev database
  -c --cleanup-db             Clean up the udev database



  • sys filesystem의 uevent의 환경변수 값 확인 (udev database정보)
$ udevadm info  /dev/mmcblk2p1 
or
$ udevadm info  -q all /dev/mmcblk2p1 
or
$ udevadm info  /sys/block/mmcblk2/mmcblk2p1  // 3개의 정보들이 거의 동일하지만,DEVLINKS정보가 조금씩 다름 
// /sys/device/..../mmcblk2p1의 uevnet 파악가능 (P는 /sys PATH)
P: /devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234/block/mmcblk2/mmcblk2p1     
N: mmcblk2p1   // /dev의 device node /dev/mmcblk2p1 
S: disk/by-id/mmc-SA02G_0x207dfb75-part1       // 상위 N의 /dev/mmcblk2p1 의 link file /dev/disk/by-id/mmc-SA02G_0x207dfb75-part1
S: disk/by-partuuid/0006c3b0-01                // 상위 N의 /dev/mmcblk2p1 의 link file /dev/disk/by-partuuid/0006c3b0-0
S: disk/by-path/platform-2198000.usdhc-part1   // 상위 N의 /dev/mmcblk2p1 의 link file /dev/disk/by-path/platform-2198000.usdhc-part1
S: disk/by-uuid/1497-59AD                      // 상위 N의 /dev/mmcblk2p1 의 link file /dev/disk/by-uuid/1497-59AD
E: DEVLINKS=/dev/disk/by-path/platform-2198000.usdhc-part1 /dev/disk/by-uuid/1497-59AD /dev/disk/by-partuuid/0006c3b0-01 /dev/disk/by-id/mmc-SA02G_0x207dfb75-part1
E: DEVNAME=/dev/mmcblk2p1
E: DEVPATH=/devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234/block/mmcblk2/mmcblk2p1
E: DEVTYPE=partition
E: ID_FS_TYPE=vfat
E: ID_FS_USAGE=filesystem
E: ID_FS_UUID=1497-59AD
E: ID_FS_UUID_ENC=1497-59AD
E: ID_FS_VERSION=FAT32
E: ID_NAME=SA02G
E: ID_PART_ENTRY_DISK=179:24
E: ID_PART_ENTRY_NUMBER=1
E: ID_PART_ENTRY_OFFSET=73036
E: ID_PART_ENTRY_SCHEME=dos
E: ID_PART_ENTRY_SIZE=3002164
E: ID_PART_ENTRY_TYPE=0xc
E: ID_PART_ENTRY_UUID=0006c3b0-01
E: ID_PART_TABLE_TYPE=dos
E: ID_PART_TABLE_UUID=0006c3b0
E: ID_PATH=platform-2198000.usdhc
E: ID_PATH_TAG=platform-2198000_usdhc
E: ID_SERIAL=0x207dfb75
E: MAJOR=179
E: MINOR=25
E: PARTN=1
E: SUBSYSTEM=block
E: TAGS=:systemd:                   //  systemd의 *.device로 파일에서 추가됨 
E: USEC_INITIALIZED=7347510      //  cat /proc/uptime 갱신된 정보시간 (boot이후)

$ udevadm info  /dev/mmcblk2
or
$ udevadm info  -q all /dev/mmcblk2
or
$ udevadm info  /sys/block/mmcblk2
P: /devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234/block/mmcblk2 // uevent 정보확인 
N: mmcblk2
S: disk/by-id/mmc-SA02G_0x207dfb75
S: disk/by-path/platform-2198000.usdhc
E: DEVLINKS=/dev/disk/by-id/mmc-SA02G_0x207dfb75 /dev/disk/by-path/platform-2198000.usdhc
E: DEVNAME=/dev/mmcblk2
E: DEVPATH=/devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234/block/mmcblk2
E: DEVTYPE=disk
E: ID_NAME=SA02G
E: ID_PART_TABLE_TYPE=dos
E: ID_PART_TABLE_UUID=0006c3b0
E: ID_PATH=platform-2198000.usdhc
E: ID_PATH_TAG=platform-2198000_usdhc
E: ID_SERIAL=0x207dfb75
E: MAJOR=179
E: MINOR=24
E: SUBSYSTEM=block
E: TAGS=:systemd:             //  systemd의 *.device로 파일에서 추가됨 
E: USEC_INITIALIZED=6995415  //  cat /proc/uptime 갱신된 정보시간 (boot이후)


TAGS=:systemd 일 경우 systemd의 *.device로 udev rule에 추가
  https://www.freedesktop.org/software/systemd/man/systemd.device.html

systemd-udevd service 

  • 좌측 Node 의미 및 분석방법 
  1. N: is for device Name in /dev
  2. S: is for Symlinks to that device name in /dev  (추후 udev/rules/에서 SYMLINK)
  3. P: is for device Path in /sys
  4. E: is for device properties in udev
  https://askubuntu.com/questions/725951/what-do-devices-environment-variable-lists-prefixes-p-n-s-e-mean


  • P: Node는 /sys의 device path이므로 이곳의 uevent 를 확인중요
uevent 중심으로 분석을 해야함
$ cat /sys/devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234/block/mmcblk2/mmcblk2p1/uevent
MAJOR=179
MINOR=25
DEVNAME=mmcblk2p1
DEVTYPE=partition
PARTN=1

$ cat /sys/devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234/block/mmcblk2/uevent
MAJOR=179
MINOR=24
DEVNAME=mmcblk2
DEVTYPE=disk


  • N: /dev의 device name 확인
$ ls /dev/mmcblk*
/dev/mmcblk2       /dev/mmcblk3       /dev/mmcblk3boot1  /dev/mmcblk3p2
/dev/mmcblk2p1     /dev/mmcblk3boot0  /dev/mmcblk3p1     /dev/mmcblk3rpmb 

  • S:  상위 N: /dev의 device name의 symbolic link list 
상위 N:의 /dev/mmclbk2 or /dev/mmcblk2p1의 /dev 내의 symbolic link 말하며,이는 DEVLINKS와 동일하다.
rule에서도 SYMLINK을 이용하여 추가도 가능함

$ ls /dev/disk/by-id/
mmc-S0J57X_0x09231300        mmc-SA02G_0x207dfb75
mmc-S0J57X_0x09231300-part1  mmc-SA02G_0x207dfb75-part1
mmc-S0J57X_0x09231300-part2

$ ls /dev/disk/by-path/
platform-2198000.usdhc        platform-219c000.usdhc-boot1
platform-2198000.usdhc-part1  platform-219c000.usdhc-part1
platform-219c000.usdhc        platform-219c000.usdhc-part2
platform-219c000.usdhc-boot0

  • E: uevent를 통해 udev 설정된 환경값 
이부분은 아래와 기본정보는 /sys 의 uevent 로 확인가능하며, 다른정보는 database에서 가져옴

  • 이외 다른 uevent 값 검색 분석 
$ find /sys -name uevent | xargs cat  // 대부분 Device 정보 와 호환정보(연결)
....
MAJOR=253
MINOR=0
DEVNAME=rtc0
OF_NAME=snvs
OF_FULLNAME=/soc/aips-bus@2000000/snvs@20cc000
OF_COMPATIBLE_0=fsl,sec-v4.0-mon
OF_COMPATIBLE_1=syscon
OF_COMPATIBLE_2=simple-mfd
OF_COMPATIBLE_N=3
...
$ find /sys -name uevent | xargs cat | grep DEVLINKS
없음 
$ find /sys -name uevent | xargs cat | grep DEVNAME
DEVNAME=mem
DEVNAME=zero
DEVNAME=kmsg
DEVNAME=full
DEVNAME=urandom
DEVNAME=null
DEVNAME=random
DEVNAME=pxp_device
DEVNAME=hwrng
DEVNAME=autofs
......

2.2 udevadm info 의 attribute 분석 

udev의 기본적인 uevent의 정보와 sys filesystem의 attribute를 분석할때, -a를 옵션을 주어 분석이 가능하다.
ATTR{x}는 해당 /sys file 주소의 값들을 출력을 해주며, 추후 rule에서도 이를 적용가능하다.

  1. uevent 정보(KERNEL/SUBSYSTEM/DRIVER) 
  2. attribute 정보(ATTR{xxx}  

parent기반으로 분석되기때문에 호출되는 순서를 파악가능하며 최종단을 주목

$ udevadm info -a /dev/mmcblk2   // /dev node로  모든 attribute를 출력 
or
$ udevadm info -a /sys/block/mmcblk2  //sys filesystem의 모든 attribute를 출력 

Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.
// 아래 looking at device 위치에 /sys file의 uevent node 확인 (최종 device의 길이 중요)
  looking at device '/devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234/block/mmcblk2':  
    KERNEL=="mmcblk2"     //device의 node name (상위 device의 마지막 node)  uevent 정보는 별도의 db를 가지고 있음 
    SUBSYSTEM=="block"    //mmcblk2의 SUBSYSTEM   
    DRIVER==""            //uevent 의 정보 
    ATTR{alignment_offset}=="0"      // cat /sys/devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234/block/mmcblk2/alignment_offset
    ATTR{capability}=="50"           // cat /sys/devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234/block/mmcblk2/capability
    ATTR{discard_alignment}=="0"     // cat /sys/devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234/block/mmcblk2/ext_range
    ATTR{ext_range}=="256"           //  ATTR{x} 모두 상동  
    ATTR{force_ro}=="0"
    ATTR{hidden}=="0"
    ATTR{inflight}=="       0        0"
    ATTR{range}=="8"
    ATTR{removable}=="0"
    ATTR{ro}=="0"
    ATTR{size}=="3842048"
    ATTR{stat}=="      95       16     6363      545        0        0        0        0        0      400      440        0        0        0        0"
// Parent device 의 uevent이며, 분석에 중요하며, SD Card Device의 정보를 얻은 시점 
  looking at parent device '/devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234':  //   
    KERNELS=="mmc2:1234"
    SUBSYSTEMS=="mmc"
    DRIVERS=="mmcblk"
    ATTRS{cid}=="02544d534130324704207dfb7500a800"     // MMC의 Register CID  
    ATTRS{csd}=="002e00325b5aa3a9ffffff800a800000"     // MMC의 Register CSD   
    ATTRS{date}=="08/2010"                             // 날짜정보, Filesystem 기준으로 생각됨  
    ATTRS{dsr}=="0x404"                                // MMC의 Register DSR  
    ATTRS{erase_size}=="512"                           // MMC의 경우 512 block 단위임  
    ATTRS{fwrev}=="0x4"
    ATTRS{hwrev}=="0x0"
    ATTRS{manfid}=="0x000002"                          // 제조사 ID  
    ATTRS{name}=="SA02G"                               // SD Card Name 
    ATTRS{ocr}=="0x00040000"                           // MMC의 Register OCR  
    ATTRS{oemid}=="0x544d"
    ATTRS{preferred_erase_size}=="4194304"
    ATTRS{rca}=="0x1234"                               // MMC의 Register RCA  
    ATTRS{scr}=="0225800001000000"                     // MMC의 Register SCR  
    ATTRS{serial}=="0x207dfb75"
    ATTRS{ssr}=="00000000000000280202900100aa0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
    ATTRS{type}=="SD"                                   // SD Card 임, eMMC가 아님  
// Parent device 의 uevent  SD Card Device를 찾은시점 
  looking at parent device '/devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2':
    KERNELS=="mmc2"
    SUBSYSTEMS=="mmc_host"
    DRIVERS==""

  looking at parent device '/devices/soc0/soc/2100000.aips-bus/2198000.usdhc':
    KERNELS=="2198000.usdhc"
    SUBSYSTEMS=="platform"
    DRIVERS=="sdhci-esdhc-imx"
    ATTRS{driver_override}=="(null)"

  looking at parent device '/devices/soc0/soc/2100000.aips-bus':
    KERNELS=="2100000.aips-bus"
    SUBSYSTEMS=="platform"
    DRIVERS==""
    ATTRS{driver_override}=="(null)"

  looking at parent device '/devices/soc0/soc':
    KERNELS=="soc"
    SUBSYSTEMS=="platform"
    DRIVERS==""
    ATTRS{driver_override}=="(null)"

  looking at parent device '/devices/soc0':
    KERNELS=="soc0"
    SUBSYSTEMS=="soc"
    DRIVERS==""
    ATTRS{family}=="Freescale i.MX"
    ATTRS{revision}=="1.4"
    ATTRS{soc_id}=="i.MX6SX"

$ udevadm info -a  /dev/mmcblk2p1  // 각 Partition 정보와 비교 

Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.
// uevent node 확인가능. 상위 node에 mmcblk2p1 추가되었으며,나머지는 동일
  looking at device '/devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234/block/mmcblk2/mmcblk2p1':
    KERNEL=="mmcblk2p1"
    SUBSYSTEM=="block"
    DRIVER==""
    ATTR{alignment_offset}=="0"
    ATTR{discard_alignment}=="354304"
    ATTR{inflight}=="       0        0"
    ATTR{partition}=="1"
    ATTR{ro}=="0"
    ATTR{size}=="3002164"
    ATTR{start}=="73036"
    ATTR{stat}=="      53       16     4275      309        0        0        0        0        0      260      270        0        0        0        0"
// 상위 (udevadm info -a /dev/mmcblk2)  동일한 device node 이며 상위와 완전동일  
  looking at parent device '/devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234/block/mmcblk2':
    KERNELS=="mmcblk2"
    SUBSYSTEMS=="block"
    DRIVERS==""
    ATTRS{alignment_offset}=="0"
    ATTRS{capability}=="50"
    ATTRS{discard_alignment}=="0"
    ATTRS{ext_range}=="256"
    ATTRS{force_ro}=="0"
    ATTRS{hidden}=="0"
    ATTRS{inflight}=="       0        0"
    ATTRS{range}=="8"
    ATTRS{removable}=="0"
    ATTRS{ro}=="0"
    ATTRS{size}=="3842048"
    ATTRS{stat}=="      95       16     6363      545        0        0        0        0        0      400      440        0        0        0        0"

  looking at parent device '/devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234':
    KERNELS=="mmc2:1234"
    SUBSYSTEMS=="mmc"
    DRIVERS=="mmcblk"
    ATTRS{cid}=="02544d534130324704207dfb7500a800"
    ATTRS{csd}=="002e00325b5aa3a9ffffff800a800000"
    ATTRS{date}=="08/2010"
    ATTRS{dsr}=="0x404"
    ATTRS{erase_size}=="512"
    ATTRS{fwrev}=="0x4"
    ATTRS{hwrev}=="0x0"
    ATTRS{manfid}=="0x000002"
    ATTRS{name}=="SA02G"
    ATTRS{ocr}=="0x00040000"
    ATTRS{oemid}=="0x544d"
    ATTRS{preferred_erase_size}=="4194304"
    ATTRS{rca}=="0x1234"
    ATTRS{scr}=="0225800001000000"
    ATTRS{serial}=="0x207dfb75"
    ATTRS{ssr}=="00000000000000280202900100aa0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
    ATTRS{type}=="SD"

  looking at parent device '/devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2':
    KERNELS=="mmc2"
    SUBSYSTEMS=="mmc_host"
    DRIVERS==""

  looking at parent device '/devices/soc0/soc/2100000.aips-bus/2198000.usdhc':
    KERNELS=="2198000.usdhc"
    SUBSYSTEMS=="platform"
    DRIVERS=="sdhci-esdhc-imx"
    ATTRS{driver_override}=="(null)"

  looking at parent device '/devices/soc0/soc/2100000.aips-bus':
    KERNELS=="2100000.aips-bus"
    SUBSYSTEMS=="platform"
    DRIVERS==""
    ATTRS{driver_override}=="(null)"

  looking at parent device '/devices/soc0/soc':
    KERNELS=="soc"
    SUBSYSTEMS=="platform"
    DRIVERS==""
    ATTRS{driver_override}=="(null)"

  looking at parent device '/devices/soc0':
    KERNELS=="soc0"
    SUBSYSTEMS=="soc"
    DRIVERS==""
    ATTRS{family}=="Freescale i.MX"
    ATTRS{revision}=="1.4"
    ATTRS{soc_id}=="i.MX6SX"


2.3  udevadm monitor를 이용확인

udevadm의 monitor를 이용하여 sdcard의 card detection 부분을 체크

$ udevadm monitor  -h
udevadm monitor [OPTIONS]

Listen to kernel and udev events.

  -h --help                                Show this help
  -V --version                             Show package version
  -p --property                            Print the event properties
  -k --kernel                              Print kernel uevents
  -u --udev                                Print udev events
  -s --subsystem-match=SUBSYSTEM[/DEVTYPE] Filter events by subsystem
  -t --tag-match=TAG                       Filter events by tag


실시간 모니터로 아래와 같이 uevent를 볼수 있으며 옵션을 추가하여 각 event를 더 확인하자.

$ udevadm monitor
monitor will print the received events for:
UDEV - the event which udev sends out after rule processing
KERNEL - the kernel uevent

mmc2: card 1234 removed
KERNEL[179853.651358] remove   /devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234/block/mmcblk2/mmcblk2p1 (block)
KERNEL[179853.654058] remove   /devices/virtual/bdi/179:24 (bdi)
KERNEL[179853.654755] remove   /devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234/block/mmcblk2 (block)
UDEV  [179853.662386] remove   /devices/virtual/bdi/179:24 (bdi)
KERNEL[179853.671233] unbind   /devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234 (mmc)
KERNEL[179853.671436] remove   /devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234 (mmc)
UDEV  [179853.699415] remove   /devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234/block/mmcblk2/mmcblk2p1 (block)
UDEV  [179853.704243] remove   /devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234/block/mmcblk2 (block)
UDEV  [179853.715698] unbind   /devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234 (mmc)
UDEV  [179853.716975] remove   /devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234 (mmc)
mmc2: host does not support reading read-only switch, assuming write-enable
mmc2: new high speed SD card at address 1234
KERNEL[179860.947683] add      /devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234 (mmc)
UDEV  [179860.956872] add      /devices/soc0/soc/2100000.aips-bummcblk2: mmc2:1234 SA02G 1.83 GiB
s/2198000.usdhc/mmc_host/mmc2/mmc2:1234 (mmc)
KERNEL[179860.966523] add      /devices/virtual/bd mmcblk2: p1
i/179:24 (bdi)
UDEV  [179860.977474] add      /devices/virtual/bdi/179:24 (bdi)
KERNEL[179860.978045] add      /devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234/block/mmcblk2 (block)
KERNEL[179860.980267] add      /devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234/block/mmcblk2/mmcblk2p1 (block)
KERNEL[179860.983182] bind     /devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234 (mmc)
UDEV  [179861.117857] add      /devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234/block/mmcblk2 (block)
FAT-fs (mmcblk2p1): Volume was not properly unmounted. Some data may be corrupt. Please run fsck.
UDEV  [179861.423592] add      /devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234/block/mmcblk2/mmcblk2p1 (block)
UDEV  [179861.426851] bind     /devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234 (mmc)


3. udev Rule 만드는 법 

udevadm info 와 monitor를 통해 기본 udev의 정보와 sys file system의 정보를 이용하여 udev rule을 간단히 만들어보자.

  • udev rule의 기본저장장소
  1. /lib/udev/rules.d/
  2. /etc/udev/rules.d/  : User는 이곳에 설정하여 추가해서 넣자 
  3. /dev/udev/rules.d/

  • Rule에서 기본적으로 match되는 정보  
  1. KERNEL : device의 kernel 이름 , device의 이름과 match
  2. SUBSYSTEM : device의 subsystem과 match
  3. DRIVER: device와 관련된 driver name과 match
  4. NAME:  /dev 에서 사용되어지는 device node와 match  
  5. SYMLINK: NAME의 대신에 사용되어지는 symbloic link list
  6. ATTRS{x}: 상위 sys filesystem의 정보와 match
  7. ENV{DEVLINKS}: 상위 E: Node 정보와 match 

  • matching 할때 pattern 
  1. *:  어느 문자들이든 match
  2. ?:  어느 한 문자만  match
  3. []:  범위를 정해서 match

  • Event 와 실행 
  1. ACTION: 해당 정보의 device가 add or remove , change가 있을 경우 
  2. RUN : 조건이 충족되면 실행을 하는 command 

RUN에 ENV{ } 정보를 출력하고 싶다면, %E{xx}로 사용가능
SYMLINK를 이용하여 /dev에 새로 device node의 symblolic link 생성가능
좀 더 사용을 하면 GOTO와 LABEL을 사용하며, 예제를 보면 쉽게 이해가 가능


3.1  MMC Device 와 udev Rule 생성 

  • MMC의 동작 rule 생성 및 적용 
mmcblk2p 가 Hotplug 될 때, add와 remove에 맞게 간단히 RUN을 사용하여 작성

$ cat /etc/udev/rules.d/10-mmc.rules  //RUN을 추가하여 지속적으로 실행가능 
# Mount and remove mmc partitions manually for 32G  
# udevadm info /dev/mmcblk2 에서 E DEVNAME 부분확인 , 상위 환경변수부분 참조

ACTION=="add" KERNEL=="mmcblk[2]p[0-9]", RUN+="/bin/mkdir -p /media/card", RUN+="/bin/mount %E{DEVNAME} /media/card"
ACTION=="remove" KERNEL=="mmcblk[2]p[0-9]", RUN+="/bin/umount -f /media/card" , RUN+="/bin/rmdir /media/card"


udev Basic Rule 사용법 (systemd-udevd.service에서 관리)
  https://www.freedesktop.org/software/systemd/man/udev.html#
  http://www.reactivated.net/writing_udev_rules.html
  https://wiki.debian.org/udev

udev Rule의 예제 및 udevadm 사용법
  https://gnu-linux.org/writing-udev-rules-for-flash-drive.html
  https://kernel.googlesource.com/pub/scm/linux/hotplug/udev/+/1ed38f41749dde482e164e692255b60c38b5d876/etc/udev/rules.d/80-drivers.rules

udev 관련 Kernel 설정
  https://wiki.gentoo.org/wiki/Udev/ko


3.2 다른 Device 와 systemd 의 Service 연결적용 

  • udev 의 device(ttyACM0) 기본분석

일반적으로 많이 사용되는 USB Serial ttyACM에 udev에 연결하여 systemd 와 함께 service 할 수 있도록 설정.

$ ls /dev/ttyACM0                // USB serial 존재파악 

$ udevadm info -a -n /dev/ttyACM0                    // udev 값 분석 및 각 ATTRS 값 확인 


// 분석방법은 아래와 같이 최종 driver 단 기준부터 그 위의 KERNEL/SUBSYSTEM/ ATTRS  중심으로 파악  
...........
  looking at device '/devices/soc0/soc/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb1/1-1/1-1.1/1-1.1:1.0/tty/ttyACM0':
    KERNEL=="ttyACM0"
    SUBSYSTEM=="tty"
    DRIVER==""

  looking at parent device '/devices/soc0/soc/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb1/1-1/1-1.1/1-1.1:1.0':
    KERNELS=="1-1.1:1.0"
    SUBSYSTEMS=="usb"
    DRIVERS=="cdc_acm"
    ATTRS{authorized}=="1"
    ATTRS{bAlternateSetting}==" 0"
    ATTRS{bInterfaceClass}=="02"
    ATTRS{bInterfaceNumber}=="00"
    ATTRS{bInterfaceProtocol}=="01"
    ATTRS{bInterfaceSubClass}=="02"
    ATTRS{bNumEndpoints}=="01"
    ATTRS{bmCapabilities}=="7"
    ATTRS{iad_bFirstInterface}=="00"
    ATTRS{iad_bFunctionClass}=="02"
    ATTRS{iad_bFunctionProtocol}=="01"
    ATTRS{iad_bFunctionSubClass}=="02"
    ATTRS{iad_bInterfaceCount}=="02"
    ATTRS{interface}=="PLSx"
    ATTRS{supports_autosuspend}=="1"

  looking at parent device '/devices/soc0/soc/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb1/1-1/1-1.1':
    KERNELS=="1-1.1"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{authorized}=="1"
    ATTRS{avoid_reset_quirk}=="0"
    ATTRS{bConfigurationValue}=="1"
    ATTRS{bDeviceClass}=="ef"
    ATTRS{bDeviceProtocol}=="01"
    ATTRS{bDeviceSubClass}=="02"
    ATTRS{bMaxPacketSize0}=="64"
    ATTRS{bMaxPower}=="100mA"
    ATTRS{bNumConfigurations}=="1"
    ATTRS{bNumInterfaces}=="14"
    ATTRS{bcdDevice}=="1730"
    ATTRS{bmAttributes}=="e0"
    ATTRS{busnum}=="1"
    ATTRS{configuration}==""
    ATTRS{devnum}=="5"
    ATTRS{devpath}=="1.1"
    ATTRS{devspec}=="  (null)"
    ATTRS{idProduct}=="005b"
    ATTRS{idVendor}=="1e2d"
    ATTRS{ltm_capable}=="no"
    ATTRS{manufacturer}=="Cinterion Wireless Modules"
    ATTRS{maxchild}=="0"
    ATTRS{product}=="PLSx"
    ATTRS{quirks}=="0x0"
    ATTRS{removable}=="unknown"
    ATTRS{rx_lanes}=="1"
    ATTRS{speed}=="480"
    ATTRS{tx_lanes}=="1"
    ATTRS{urbnum}=="122"
    ATTRS{version}==" 2.00"
.............
  looking at parent device '/devices/soc0/soc/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb1':
    KERNELS=="usb1"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{authorized}=="1"
    ATTRS{authorized_default}=="1"
    ATTRS{avoid_reset_quirk}=="0"
    ATTRS{bConfigurationValue}=="1"
    ATTRS{bDeviceClass}=="09"
    ATTRS{bDeviceProtocol}=="01"
    ATTRS{bDeviceSubClass}=="00"
    ATTRS{bMaxPacketSize0}=="64"
    ATTRS{bMaxPower}=="0mA"
    ATTRS{bNumConfigurations}=="1"
    ATTRS{bNumInterfaces}==" 1"
    ATTRS{bcdDevice}=="0419"
    ATTRS{bmAttributes}=="e0"
    ATTRS{busnum}=="1"
    ATTRS{configuration}==""
    ATTRS{devnum}=="1"
    ATTRS{devpath}=="0"
    ATTRS{idProduct}=="0002"
    ATTRS{idVendor}=="1d6b"
    ATTRS{interface_authorized_default}=="1"
    ATTRS{ltm_capable}=="no"
    ATTRS{manufacturer}=="Linux 4.19.35-1.1.0+g0f9917c ehci_hcd"
    ATTRS{maxchild}=="1"
    ATTRS{product}=="EHCI Host Controller"
    ATTRS{quirks}=="0x0"
    ATTRS{removable}=="unknown"
    ATTRS{rx_lanes}=="1"
    ATTRS{serial}=="ci_hdrc.1"
    ATTRS{speed}=="480"
    ATTRS{tx_lanes}=="1"
    ATTRS{urbnum}=="25"
    ATTRS{version}==" 2.00"
.....

// USB CDC 중 ACM은 일반적으로 USB Serial로 많이 사용되지만, 꼭 Serial으로만 사용해야하는 것은 아니다. 
// 세부사항은 USB CDC 종류에서 각각 파악하자  

$ udevadm info -a -n /dev/ttyACM0 | grep serial  // ttyACM0을 USB Serial로 사용하기 위해 serial 이름파악 
ATTRS{serial}=="ci_hdrc.1"

  • udev 의 device(ttyACM0) 와 systemd 의 service 연결
각 udev rule에서 ttyACM 관련부분을 검색 한 후 이를 분석한 후, 직접 수정
$ find /etc/udev/rules.d/  -name *ttyACM*  // udev file 찾기 (우선순위 etc -> lib) 못찾으면 grep 사용 
$ find /lib/udev/rules.d/  -name *ttyACM*  

// 나의 경우, KERENL에, ttyACM0을 넣고, serial을 더 좀 더 확실히 하기 위해 ATTRS{serial} 추가했지만, 자기 구성대로 변경
// SYSTEMD_WANTS 사용시 udev database에 TAG+="systemd" 넣지 않는다면, systemd에서 찾지 못한다 (세부내용은 Manual)  
// 이기능은 systemd의 Want=에 추가되며, 추후 systemd의 *.socket 의 BindToDevice= 와 연결가능 

$ cat /etc/udev/rules.d/20-ttyACM0.rules  // KERNEL의 Device 와 Serial 이름으로 동작 
KERNEL=="ttyACM0", ATTRS{serial}=="ci_hdrc.1" , TAG+="systemd", ENV{SYSTEMD_WANTS}="my.service"

udev Rule에 TAG+="systemd"와 ENV{SYSTEMD_WANTS} 와 udev Database
  https://www.freedesktop.org/software/systemd/man/systemd.device.html
  https://www.freedesktop.org/software/systemd/man/udev.html#

  • 연결될 systemd의 service 구성

systemd의 service 중 (BindToDevice대신) BindTo 와 After 부분설정을 위해 각 값 검색
$ systemctl list-units --all --full   //  systemctl list-units --all --full 의 정보가 너무 많음 
$ systemctl list-units --all --full | grep ".device"   //  systemctl list-units --all --full 의 정보가 너무 많아 device만 찾음 

// device 구성을 보면, parent가 존재하므로, 점점 node가 길어지면, 최종으로 load되는 부분을 찾아야함 
// systemd.device에서 ttyACM0 or 상위 ATTR 값을 넣어 검색범위를 좁힘 
$ systemctl list-units --all --full | grep ".device" | grep "ci_hdrc.1" // systemd.device 에 상위 ATTR 값 동일부분확인
  dev-serial-by\x2dpath-platform\x2dci_hdrc.1\x2dusb\x2d0:1.1:1.0.device                                              loaded    active   plugged   PLSx         
  dev-serial-by\x2dpath-platform\x2dci_hdrc.1\x2dusb\x2d0:1.1:1.2.device                                              loaded    active   plugged   PLSx         
  dev-serial-by\x2dpath-platform\x2dci_hdrc.1\x2dusb\x2d0:1.1:1.4.device                                              loaded    active   plugged   PLSx         
  dev-serial-by\x2dpath-platform\x2dci_hdrc.1\x2dusb\x2d0:1.1:1.6.device                                              loaded    active   plugged   PLSx         
  dev-serial-by\x2dpath-platform\x2dci_hdrc.1\x2dusb\x2d0:1.1:1.8.device                                              loaded    active   plugged   PLSx         
  sys-devices-soc0-soc-2100000.aips\x2dbus-2184200.usb-ci_hdrc.1-usb1-1\x2d1-1\x2d1.1-1\x2d1.1:1.0-tty-ttyACM0.device loaded    active   plugged   PLSx         
  sys-devices-soc0-soc-2100000.aips\x2dbus-2184200.usb-ci_hdrc.1-usb1-1\x2d1-1\x2d1.1-1\x2d1.1:1.10-net-usb0.device   loaded    active   plugged   PLSx         
  sys-devices-soc0-soc-2100000.aips\x2dbus-2184200.usb-ci_hdrc.1-usb1-1\x2d1-1\x2d1.1-1\x2d1.1:1.12-net-usb1.device   loaded    active   plugged   PLSx         
  sys-devices-soc0-soc-2100000.aips\x2dbus-2184200.usb-ci_hdrc.1-usb1-1\x2d1-1\x2d1.1-1\x2d1.1:1.2-tty-ttyACM1.device loaded    active   plugged   PLSx         
  sys-devices-soc0-soc-2100000.aips\x2dbus-2184200.usb-ci_hdrc.1-usb1-1\x2d1-1\x2d1.1-1\x2d1.1:1.4-tty-ttyACM2.device loaded    active   plugged   PLSx         
  sys-devices-soc0-soc-2100000.aips\x2dbus-2184200.usb-ci_hdrc.1-usb1-1\x2d1-1\x2d1.1-1\x2d1.1:1.6-tty-ttyACM3.device loaded    active   plugged   PLSx         
  sys-devices-soc0-soc-2100000.aips\x2dbus-2184200.usb-ci_hdrc.1-usb1-1\x2d1-1\x2d1.1-1\x2d1.1:1.8-tty-ttyACM4.device loaded    active   plugged   PLSx

$ systemctl list-units --all --full | grep ".device" | grep "ttyACM0" // systemd.device 에 ttyACM0 재확인 
  dev-ttyACM0.device                                                                                                  loaded    active   plugged   PLSx         
  sys-devices-soc0-soc-2100000.aips\x2dbus-2184200.usb-ci_hdrc.1-usb1-1\x2d1-1\x2d1.1-1\x2d1.1:1.0-tty-ttyACM0.device loaded    active   plugged   PLSx

udev Rule에 같이 동작할 systemd 의 service 설정
**system unit 과 system.service manual 참조
//상위 udev의 Rule에서 적용했던 부분이 동작할 경우 실행 (ttyACM0) 
//Unit의 BindTo 와 After를 *.service로만 한정지어 생각했는데, device를 비롯하여 mount 등 모두 가능
//Unit의 대상은 모든 systemd의 설정의 기본이며, service/socket/device/mount/등 모두 적용대상
$ vi /lib/systemd/system/my.service 
or 
$ vi /etc/systemd/system/my.service 
[Unit]
Description=TEST Service for ttyACM0
BindsTo=sys-devices-soc0-soc-2100000.aips\x2dbus-2184200.usb-ci_hdrc.1-usb1-1\x2d1-1\x2d1.1-1\x2d1.1:1.0-tty-ttyACM0.device
After=sys-devices-soc0-soc-2100000.aips\x2dbus-2184200.usb-ci_hdrc.1-usb1-1\x2d1-1\x2d1.1-1\x2d1.1:1.0-tty-ttyACM0.device

# BindsTo 는 Requires 와 유사하게 dependencies를 요구하는 설정이며, Requres 보다 좀 더 강력하다고 하며, 
# After와 함께 같이 사용할때 최적이라고 한다.
# 주의 할 것은 Fail 될 경우, Skip되므로 이 부분 주의하며, 상위 Device가 연결될때 Timing을 기다림

[Service]
ExecStart=test start 

[Install]
WantedBy=multi-user.target

  1. udev에서 ttyACM0 상위정보의 uevent가 오면 이를 udev에 TAG를 사용하여 systemd에 노출하고 service로 연결
  2. 상위 service에서 AfterBindsTo는 systemd의 service에 연결하여 Timing을 조절(제대로 붙기전에는 실행 불가능) 

아래의 사이트에서 쉽게 찾아 연결했으며, 세부내용은 아래사이트 참조

systemd의 unit 과 service 설정정보
  https://www.freedesktop.org/software/systemd/man/systemd.unit.html
  https://www.freedesktop.org/software/systemd/man/systemd.unit.html#Mapping%20of%20unit%20properties%20to%20their%20inverses
  https://www.freedesktop.org/software/systemd/man/systemd.service.html#


$ udevadm info /dev/ttyACM0 // 상위 실행 후 동작확인 
P: /devices/soc0/soc/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb1/1-1/1-1.1/1-1.1:1.0/tty/ttyACM0
N: ttyACM0
S: serial/by-id/usb-Cinterion_Wireless_Modules_PLSx-if00
S: serial/by-path/platform-ci_hdrc.1-usb-0:1.1:1.0
E: DEVLINKS=/dev/serial/by-path/platform-ci_hdrc.1-usb-0:1.1:1.0 /dev/serial/by-id/usb-Cinterion_Wireless_Modules_PLSx-if00
E: DEVNAME=/dev/ttyACM0
E: DEVPATH=/devices/soc0/soc/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb1/1-1/1-1.1/1-1.1:1.0/tty/ttyACM0
E: ID_BUS=usb
E: ID_MODEL=PLSx
E: ID_MODEL_ENC=PLSx
E: ID_MODEL_ID=005b
E: ID_PATH=platform-ci_hdrc.1-usb-0:1.1:1.0
E: ID_PATH_TAG=platform-ci_hdrc_1-usb-0_1_1_1_0
E: ID_REVISION=1730
E: ID_SERIAL=Cinterion_Wireless_Modules_PLSx
E: ID_TYPE=generic
E: ID_USB_CLASS_FROM_DATABASE=Miscellaneous Device
E: ID_USB_DRIVER=cdc_acm
E: ID_USB_INTERFACES=:020201:0a0000:020200:020600:
E: ID_USB_INTERFACE_NUM=00
E: ID_USB_PROTOCOL_FROM_DATABASE=Interface Association
E: ID_VENDOR=Cinterion_Wireless_Modules
E: ID_VENDOR_ENC=Cinterion\x20Wireless\x20Modules
E: ID_VENDOR_ID=1e2d
E: MAJOR=166
E: MINOR=0
E: SUBSYSTEM=tty
E: SYSTEMD_WANTS=my.service   // systemd service 확인 
E: TAGS=:systemd:             // TAG의 systemd 추가 확인 
E: USEC_INITIALIZED=19217285

udev 와 systemd 연결
  https://unix.stackexchange.com/questions/89691/how-do-i-connect-a-3g-dongle-using-systemd

systemd 기본사용법
  https://ahyuo79.blogspot.com/2020/01/systemd.html


4. udevadm test 와 trigger를 이용하여 테스트 

새로 만든 udev rule에 ACTION Event를 주어 SW로만 테스트 진행가능하며, 본인이 좀 더 세부 테스트를 한다면, 다양한 옵션설정도 가능.

아래의 두가지 방식으로 테스트 가능

  • udev 의 테스트 방식 

$ udevadm test -h
$ udevadm test [OPTIONS] DEVPATH

Test an event run.

  -h --help                            Show this help
  -V --version                         Show package version
  -a --action=ACTION                   Set action string
  -N --resolve-names=early|late|never  When to resolve names


  • udev에 uevent를 주어 테스트 진행 

 $ udevadm trigger  -h
udevadm trigger [OPTIONS] DEVPATH

Request events from the kernel.

  -h --help                         Show this help
  -V --version                      Show package version
  -v --verbose                      Print the list of devices while running
  -n --dry-run                      Do not actually trigger the events
  -t --type=                        Type of events to trigger
          devices                     sysfs devices (default)
          subsystems                  sysfs subsystems and drivers
  -c --action=ACTION                Event action value, default is "change"
  -s --subsystem-match=SUBSYSTEM    Trigger devices from a matching subsystem
  -S --subsystem-nomatch=SUBSYSTEM  Exclude devices from a matching subsystem
  -a --attr-match=FILE[=VALUE]      Trigger devices with a matching attribute
  -A --attr-nomatch=FILE[=VALUE]    Exclude devices with a matching attribute
  -p --property-match=KEY=VALUE     Trigger devices with a matching property
  -g --tag-match=KEY=VALUE          Trigger devices with a matching property
  -y --sysname-match=NAME           Trigger devices with this /sys path
     --name-match=NAME              Trigger devices with this /dev name
  -b --parent-match=NAME            Trigger devices with that parent device
  -w --settle                       Wait for the triggered events to complete


실제테스트 진행 
  • 상위 만들어진 rule에 SW로 테스트 진행 (문제발생)
$ udevadm test -a remove /dev/mmcblk2
or
$ udevadm test -a remove  /sys/block/mmcblk2
calling: test
version 239
This program is for debugging only, it does not run any program
specified by a RUN key. It may show incorrect results, because
some values may be different, or not available at a simulation run.

Load module index
Skipping empty file: /etc/systemd/network/99-default.link
Created link configuration context.
Reading rules file: /etc/udev/rules.d/10-imx.rules
Reading rules file: /etc/udev/rules.d/30-mmc.rules
Reading rules file: /lib/udev/rules.d/50-firmware.rules
Reading rules file: /lib/udev/rules.d/50-udev-default.rules
Reading rules file: /lib/udev/rules.d/60-block.rules
Reading rules file: /lib/udev/rules.d/60-cdrom_id.rules
Reading rules file: /lib/udev/rules.d/60-drm.rules
Reading rules file: /lib/udev/rules.d/60-evdev.rules
Reading rules file: /lib/udev/rules.d/60-input-id.rules
Reading rules file: /lib/udev/rules.d/60-persistent-alsa.rules
Reading rules file: /lib/udev/rules.d/60-persistent-input.rules
Reading rules file: /lib/udev/rules.d/60-persistent-storage-tape.rules
Reading rules file: /lib/udev/rules.d/60-persistent-storage.rules
Reading rules file: /lib/udev/rules.d/60-persistent-v4l.rules
Reading rules file: /lib/udev/rules.d/60-sensor.rules
Reading rules file: /lib/udev/rules.d/60-serial.rules
Reading rules file: /lib/udev/rules.d/64-btrfs.rules
Reading rules file: /lib/udev/rules.d/70-joystick.rules
Reading rules file: /lib/udev/rules.d/70-mouse.rules
Reading rules file: /lib/udev/rules.d/70-power-switch.rules
Reading rules file: /lib/udev/rules.d/70-touchpad.rules
Reading rules file: /lib/udev/rules.d/70-uaccess.rules
Reading rules file: /lib/udev/rules.d/71-seat.rules
Reading rules file: /lib/udev/rules.d/73-seat-late.rules
Reading rules file: /lib/udev/rules.d/75-net-description.rules
Reading rules file: /lib/udev/rules.d/75-probe_mtd.rules
Reading rules file: /lib/udev/rules.d/78-sound-card.rules
Reading rules file: /lib/udev/rules.d/80-drivers.rules
Reading rules file: /lib/udev/rules.d/80-net-setup-link.rules
Reading rules file: /lib/udev/rules.d/90-alsa-restore.rules
Reading rules file: /lib/udev/rules.d/90-vconsole.rules
Reading rules file: /lib/udev/rules.d/97-hid2hci.rules
Reading rules file: /lib/udev/rules.d/99-systemd.rules
Reading rules file: /etc/udev/rules.d/touchscreen.rules
rules contain 24576 bytes tokens (2048 * 12 bytes), 11107 bytes strings
1602 strings (19400 bytes), 1040 de-duplicated (8856 bytes), 563 trie nodes used
unable to open device '/sys/dev/mmcblk2'   //문제발생 /sys/dev/의 구조가 다르며, /sys로 변경해도 동일, /dev/mmcblk2 현재없어서 인것 같음 
Unload module index
Unloaded link configuration context.

$ udevadm test -a add /dev/mmcblk2 
$ udevadm test -a add  /sys/block/mmcblk2

다시 trigger 기반으로 테스트진행시 문제없음 
  • 상위 만들어진 rule에 SW로 테스트 진행 (문제없음)
$ udevadm trigger -c add /dev/mmcblk2   // RUN 동작확인 
$ udevadm trigger -c remove /dev/mmcblk2 // RUN 동작확인