הדמיית רשת Thread עם OpenThread

1. מבוא

26b7f4f6b3ea0700.png

Openthread ש-Google פרסמה הוא הטמעת קוד פתוח של פרוטוקול הרשת Thread. Google Nest השיקה את OpenThread, כדי שטכנולוגיה המשמשת במוצרי Nest תהיה זמינה באופן נרחב למפתחים כדי להאיץ את פיתוח המוצרים לבית החכם.

המפרט של Thread מגדיר פרוטוקול תקשורת אמין, מאובטח וחזק עם חיבור Bluetooth למכשירים שונים, לשימוש באפליקציות ביתיות. Openthread מיישם את כל שכבות הרשת של Thread, כולל IPv6, 6LoWPAN, IEEE 802.15.4 עם אבטחת MAC, תשתית לקישור רשת וניתוב רשת.

Codelab זה ידריך אתכם בסימולציה של רשת Thread במכשירים מדומים.

מה תלמדו

  • איך מגדירים את ארגז הכלים של Openthread
  • איך מדמים רשת של Thread
  • איך לאמת צמתים של שרשור
  • איך לנהל רשת של Thread עם OpenThread Daemon

מה הדרישות כדי להצטרף לתוכנית?

  • Git
  • ידע בסיסי ב-Linux, ניתוב רשתות

2. הגדרה של מערכת ה-build

Git

יש צורך ב-Git כדי להשלים את ה-Codelab הזה. צריך להוריד ולהתקין אותו לפני שממשיכים.

לאחר ההתקנה, פועלים לפי ההוראות של מערכת ההפעלה הספציפית כדי להוריד ולפתח את OpenThread.

XCode ל-Mac OS X

נדרש קוד X להתקנה ולבנייה של OpenThread ב-Mac OS X.

לאחר התקנת XCode, התקן את כלי XCode Command Line:

$ xcode-select --install

תמיכה ב-Linux / Mac OS X

הוראות ההתקנה האלה נבדקו ב-Ubuntu Server 14.04 LTS וב-Mac OS X Sierra 10.12.6.

מתקינים את OpenThread. הפקודות bootstrap מוודאות שארגז הכלים מותקן ושהסביבה מוגדרת כראוי:

$ mkdir -p ~/src
$ cd ~/src
$ git clone --recursive https://github.com/openthread/openthread.git
$ cd openthread
$ ./script/bootstrap

שימוש ב-Windows

אם אתם מעדיפים את Windows, מומלץ לנסות את הגרסה של Docker של Codelab זה.

3. פיתוח אפליקציות OpenThread

לאחר השלמת ההתקנה, בנה את יישום OpenThread לדוגמה. ב-Codelab הזה אנחנו משתמשים בדוגמת הסימולציה.

$ cd ~/src/openthread
$ ./script/cmake-build simulation

עכשיו, צרו את OpenThread Daemon:

$ ./script/cmake-build posix -DOT_DAEMON=ON

4. סימולציה של רשת שרשורים

האפליקציה לדוגמה שבה תשתמשו ב-Codelab הזה מדגימה אפליקציית מינימום של OpenThread שחושפת את ממשקי התצורה והניהול של OpenThread דרך ממשק שורת הפקודה (CLI) בסיסי.

התרגיל הזה כולל את השלבים המינימליים שצריך לבצע כדי לשלוח סימולציה של מכשיר Thread עם סימולציה של שרשור מתח אחר.

האיור הבא מתאר טופולוגיה בסיסית של רשת שרשור. לצורך תרגיל זה נדמות את שני הצמתים שבעיגול הירוק: מוביל שרשור ונתב שרשור עם חיבור יחיד ביניהם.

6e3aa07675f902dc.png

פינג לצומת

1. התחלה של צומת 1

צריך לעבור לספרייה openthread ולייצר תהליך CLI למכשיר מדומה Thread באמצעות הקובץ הבינארי ot-cli-ftd.

$ cd ~/src/openthread
$ ./build/simulation/examples/apps/cli/ot-cli-ftd 1

הערה: אם ההודעה > לא מופיעה אחרי הרצת הפקודה הזו, מקישים על enter.

הקובץ הבינארי הזה מטמיע מכשיר OpenThread שמדמה את ה-POSIX. מנהל התקן הרדיו IEEE 802.15.4 מוטמע על גבי UDP (מסגרות IEEE 802.15.4 עוברות בתוך מטען ייעודי (payload) של UDP).

הארגומנט של 1 הוא מתאר קובץ שמייצג את הביטים בעלי המשמעות הנמוכה ביותר של ה-IEEE EUI-64 "המוקצים על ידי היצרן". הערך הזה משמש גם בעת קישור ליציאת UDP לאמולציה של רדיו IEEE 802.15.4 (יציאה = 9000 + מתאר הקובץ). כל מופע של מכשיר שרשור מדומה ב-Codelab הזה ישתמש במתאר קובץ שונה.

הערה: יש להשתמש מתארי קבצים של 1 או יותר, כפי שמצוין ב-Codelab הזה, בזמן יצירת תהליך במכשיר מדומה. מתאר הקובץ של 0 שמור לשימוש אחר.

צריך ליצור מערך נתונים תפעולי חדש ולהקציב אותו כמערך הפעיל. מערך הנתונים התפעולי הוא התצורה של רשת השרשורים שיוצרים.

> dataset init new
Done
> dataset
Active Timestamp: 1
Channel: 20
Channel Mask: 07fff800
Ext PAN ID: d6263b6d857647da
Mesh Local Prefix: fd61:2344:9a52:ede0/64
Network Key: e4344ca17d1dca2a33f064992f31f786
Network Name: OpenThread-c169
PAN ID: 0xc169
PSKc: ebb4f2f8a68026fc55bcf3d7be3e6fe4
Security Policy: 0, onrcb
Done

מגדירים את מערך הנתונים הזה כמערך הפעיל:

> dataset commit active
Done

מציגים את ממשק IPv6:

> ifconfig up
Done

הפעלה של פרוטוקול Thread:

> thread start
Done

ממתינים כמה שניות ומוודאים שהמכשיר הופך למנהיג השרשורים. ה-Leader הוא המכשיר שאחראי על ניהול ההקצאה של מזהה הנתב.

> state
leader
Done

הצג את כתובות ה-IPv6 שהוקצו לממשק Thread של צומת 1 (הפלט שלך יהיה שונה):

> ipaddr
fd61:2344:9a52:ede0:0:ff:fe00:fc00
fd61:2344:9a52:ede0:0:ff:fe00:5000
fd61:2344:9a52:ede0:d041:c5ba:a7bc:5ce6
fe80:0:0:0:94da:92ea:1353:4f3b
Done

שימו לב לסוגים הספציפיים של כתובות IPv6:

  • מתחיל ב-fd = mesh-local
  • מתחיל ב-fe80 = link-local

סוגי הכתובות מסוג 'רשת מקומית' מסווגים עוד יותר:

  • מכיל ff:fe00 = מאתר הנתב (RLOC)
  • לא מכיל ff:fe00 = מזהה נקודת קצה (EID)

מזהים את ה-EID בפלט של המסוף, ורושמים אותו לשימוש מאוחר יותר. בפלט לדוגמה שלמעלה, ה-EID הוא:

fd61:2344:9a52:ede0:d041:c5ba:a7bc:5ce6

2. התחלת צומת 2

פותחים טרמינל חדש ועוברים לספרייה של openthread כדי ליצור את תהליך ה-CLI. זהו הסימולטור השני בשרשור:

$ cd ~/src/openthread
$ ./build/simulation/examples/apps/cli/ot-cli-ftd 2

הערה: אם ההודעה > לא מופיעה אחרי הרצת הפקודה הזו, מקישים על enter.

מגדירים את מפתח הרשת של Thread ומזהה ה-PAN, באמצעות אותם ערכים כמו מערך הנתונים התפעולי של צומת 1:

> dataset networkkey e4344ca17d1dca2a33f064992f31f786
Done
> dataset panid 0xc169
Done

מגדירים את מערך הנתונים הזה כמערך הפעיל:

> dataset commit active
Done

מציגים את ממשק IPv6:

> ifconfig up
Done

הפעלה של פרוטוקול Thread:

> thread start
Done

המכשיר יופעל בעצמו כילד. צאצא חוטי מקביל למכשיר קצה, שהוא מכשיר שרשור שמשדר ומקבל תנועה חד-פעמית רק עם מכשיר הורה.

> state
child
Done

תוך 2 דקות אמור להופיע מצב מעבר מ-child ל-router. נתב שרשור יכול לנתב תנועה בין מכשירים שונים. הוא נקרא גם 'הורה'.

> state
router
Done

אימות הרשת

דרך קלה לאמת את רשת האריג היא לבדוק את טבלת הנתב.

1. בדיקת הקישוריות

בצומת 2, מקבלים את RLOC16. RLOC16 הוא 16 הביטים האחרונים בכתובת RLOC IPv6 במכשיר.

> rloc16
5800
Done

בצמתים 1, מחפשים את טבלת הנתב RLOC1 של צומת 2. קודם צריך לוודא שצומת 2 עבר למצב נתב.

> router table
| ID | RLOC16 | Next Hop | Path Cost | LQI In | LQI Out | Age | Extended MAC  |
+----+--------+----------+----------+-------+---------+-----+------------------+
| 20 | 0x5000 |       63 |         0 |     0 |      0 |   0 | 96da92ea13534f3b |
| 22 | 0x5800 |       63 |         0 |     3 |      3 |  23 | 5a4eb647eb6bc66c |

טבלת ה-RLOC של צומת 1 של 0xa800 נמצאת בטבלה, ומאשרת שהיא מחוברת לרשת.

2. פינג צומת 1 מצומת 2

בדיקת הקישוריות בין שני המכשירים המדומים בשרשור. בצומת 2, ping ה-EID שהוקצה לצומת 1:

> ping fd61:2344:9a52:ede0:d041:c5ba:a7bc:5ce6
> 16 bytes from fd61:2344:9a52:ede0:d041:c5ba:a7bc:5ce6: icmp_seq=1
hlim=64 time=12ms

יש ללחוץ על enter כדי לחזור להודעת ה-CLI של >.

בדיקת הרשת

עכשיו כשאתם יכולים לשלוח פינג בין שני מכשירי שרשור מדומים, עליכם לבדוק את רשת האריג הזו על ידי העברה של צומת אחד אופליין.

חוזרים לצומת 1 ומפסיקים את השרשור:

> thread stop
Done

עוברים לצומת 2 ובודקים את המצב. תוך שתי דקות, צומת 2 מזהה שהמוביל (צומת 1) לא מקוון, והמעבר של צומת 2 צריך להיות leader של הרשת:

> state
router
Done
...
> state
leader
Done

לאחר האישור, עצרו את השרשור ואפסו את צומת 2 להגדרות המקוריות לפני היציאה. מתבצע איפוס להגדרות המקוריות כדי לוודא שפרטי הכניסה לרשת של Thread שבהם השתמשנו בתרגיל הזה לא יועברו לתרגיל הבא.

> thread stop
Done
> factoryreset
>
> exit

איפוס להגדרות המקוריות ויציאה מצומת 1:

> factoryreset
>
> exit

מידע נוסף על כל הפקודות הזמינות ב-CLI זמין בחומר העזר בנושא CLI.

5. אימות צמתים באמצעות 'עמלות'

בתרגיל הקודם, הגדרתם רשת Thread עם שני מכשירים מדומים וקישוריות מאומתת. עם זאת, הפעולה הזו מאפשרת רק מעבר של תעבורת נתונים מקומית לא מאומתת מסוג IPv6 בין מכשירים. כדי לנתב תנועה גלובלית בפרוטוקול IPv6 (ודרך האינטרנט באמצעות נתב גבולות שרשור), צריך לאמת את הצמתים.

כדי לבצע אימות, מכשיר אחד חייב לפעול כנציב. הנציב הוא שרת האימות שנבחר כעת למכשירי Thread החדשים, והוא מאשר לספק את פרטי הכניסה לרשת הנדרשים למכשירים כדי להצטרף לרשת.

בתרגיל הזה, נשתמש באותה טופולוגיה של שני צמתים כמו קודם. לאימות, מנהל השרשורים יפעל כנציב, נתב השרשורים בתור משתתף.

d6a67e8a0d0b5dcb.png

1. יצירת רשת

אם ממשיכים מהתרגיל הקודם, אמורים להיות לך כבר שני חלונות פתוחים. אם לא, צריך לוודא ששתיים פתוחות ומוכנות לשימוש. האחד ישמש כצומת 1, והשני צומת 2.

בשדה 'צומת 1', יוצרים את תהליך ה-CLI:

$ cd ~/src/openthread
$ ./build/simulation/examples/apps/cli/ot-cli-ftd 1

הערה: אם ההודעה > לא מופיעה אחרי הרצת הפקודה הזו, מקישים על enter.

יוצרים מערך נתונים תפעולי חדש, מקצים אותו כמערך הפעיל ומתחילים שרשור:

> dataset init new
Done
> dataset
Active Timestamp: 1
Channel: 12
Channel Mask: 07fff800
Ext PAN ID: e68d05794bf13052
Mesh Local Prefix: fd7d:ddf7:877b:8756/64
Network Key: a77fe1d03b0e8028a4e13213de38080e
Network Name: OpenThread-8f37
PAN ID: 0x8f37
PSKc: f9debbc1532487984b17f92cd55b21fc
Security Policy: 0, onrcb
Done

מגדירים את מערך הנתונים הזה כמערך הפעיל:

> dataset commit active
Done

מציגים את ממשק IPv6:

> ifconfig up
Done

הפעלה של פרוטוקול Thread:

> thread start
Done

ממתינים כמה שניות ומוודאים שהמכשיר קיבל את הסטטוס 'מנהיג שרשור':

> state
leader
Done

2. הפעלת תפקיד הנציב

כשאתם עדיין נמצאים בצומת 1, התחילו את תפקיד הנציב:

> commissioner start
Done

מאפשרים לכל משתתף (באמצעות תו כללי לחיפוש *) להזין את פרטי ההתחברות של J01NME למשתמש לבצע עמלה על הרשת. Shareder הוא מכשיר שאדמין אנושי הוסיף אותו לרשת שרשור מקובלת.

> commissioner joiner add * J01NME
Done

3. הפעלת התפקיד 'הצטרפות'

בחלון הטרמינל השני, מריצים תהליך חדש של CLI. זהו צומת 2.

$ cd ~/src/openthread
$ ./build/simulation/examples/apps/cli/ot-cli-ftd 2

בצומת 2, מפעילים את התפקיד 'הצטרפות' באמצעות פרטי הכניסה של J01NME.

> ifconfig up
Done
> joiner start J01NME
Done

... ממתינים כמה שניות לאישור ...

Join success

כמכשיר מצורף, המכשיר (צומת 2) אימת את עצמו בפני הנציב (צומת 1) וקיבל את פרטי הכניסה של Thread Network.

לאחר שהמערכת מאמתת את צומת 2, מתחילים את השרשור:

> thread start
Done

4. אימות הרשת

בדוק את state בצומת 2 כדי לוודא שהוא הצטרף לרשת. תוך שתי דקות, צומת 2 עובר מ-child ל-router:

> state
child
Done
...
> state
router
Done

5. איפוס ההגדרות

כדי להתכונן לתרגיל הבא, יש לאפס את ההגדרות. בכל צומת, מפסיקים את השרשור, מבצעים איפוס להגדרות המקוריות ויוצאים ממכשיר הסימולציה (Thread):

> thread stop
Done
> factoryreset
>
> exit

יכול להיות שיהיה צורך ללחוץ על enter כמה פעמים כדי להחזיר את ההודעה > אחרי הפקודה factoryreset.

6. ניהול הרשת באמצעות OpenThread Daemon

במסגרת התרגיל הזה, ננסה סימולציה של מופע CLI אחד (מכשיר SoC Thread מוטמע אחד) ומופע אחד של רדיו-מעבד (RCP).

ot-daemon הוא מצב של אפליקציית OpenThread Posix שמשתמשת בשקע UNIX כקלט ופלט, כך שהליבה של OpenThread יכולה לפעול בתור שירות. לקוח יכול לתקשר עם שירות זה על ידי התחברות לשקע באמצעות הפרוטוקול OpenCLI CLI.

ot-ctl הוא שירות CLI שמסופק על ידי ot-daemon לניהול ולהגדרה של ה-RCP. באמצעות הפעולה הזו, נחבר את ה-RCP לרשת שנוצרה על ידי ה-Thread.

שימוש ב-ot-daemon

בתרגיל הזה ייעשה שימוש בשלושה חלונות טרמינל, בהתאם לשלבים הבאים:

  1. מופע CLI של מכשיר מחולק לשרשורים (צומת 1)
  2. תהליך ot-daemon
  3. מופע אחד (CLI) של ot-ctl

אם ממשיכים מהתרגיל הקודם, אמורים להיות לך כבר שני חלונות פתוחים. פותחים שליש כדי לוודא שיש לכם שלושה חלונות טרמינל זמינים לתרגיל הזה.

1. התחלה של צומת 1

בחלון הטרמינל הראשון, יוצרים את תהליך ה-CLI למכשיר עם שרשור הסימולציה:

$ cd ~/src/openthread
$ ./build/simulation/examples/apps/cli/ot-cli-ftd 1

הערה: אם ההודעה > לא מופיעה אחרי הרצת הפקודה הזו, מקישים על enter.

יוצרים מערך נתונים תפעולי חדש, מקצים אותו כמערך הפעיל ומתחילים שרשור:

> dataset init new
Done
> dataset
Active Timestamp: 1
Channel: 13
Channel Mask: 07fff800
Ext PAN ID: 97d584bcd493b824
Mesh Local Prefix: fd55:cf34:dea5:7994/64
Network Key: ba6e886c7af50598df1115fa07658a83
Network Name: OpenThread-34e4
PAN ID: 0x34e4
PSKc: 38d6fd32c866927a4dfcc06d79ae1192
Security Policy: 0, onrcb
Done

מגדירים את מערך הנתונים הזה כמערך הפעיל:

> dataset commit active
Done

מציגים את ממשק IPv6:

> ifconfig up
Done

הפעלה של פרוטוקול Thread:

> thread start
Done

הצגת כתובות ה-IPv6 שהוקצו לממשק Thread של צומת 1:

> ipaddr
fd55:cf34:dea5:7994:0:ff:fe00:fc00
fd55:cf34:dea5:7994:0:ff:fe00:d000
fd55:cf34:dea5:7994:460:872c:e807:c4ab
fe80:0:0:0:9cd8:aab6:482f:4cdc
Done
>

כפי שמוסבר בשלב סימולציה של רשת שרשור, כתובת אחת היא קישור מקומי (fe80) ושלוש הן רשת מקומית (fd). ה-EID הוא הכתובת המקומית ברשת שלא מכילה ff:fe00 בכתובת. בפלט לדוגמה הזה, ה-EID הוא fd55:cf34:dea5:7994:460:872c:e807:c4ab.

מזהה ה-EID הספציפי של פלט ipaddr שישמש לתקשורת עם הצומת.

2. התחלה של da-daemon

בחלון המסוף השני, עוברים לספרייה openthread, ומתחילים ב-ot-daemon עבור צומת RCP, שנקרא 'צומת 2'. מומלץ להשתמש בסימון המפורט של -v כדי לראות פלט ביומן ולוודא שהוא פועל, ולוודא להשתמש ב-sudo:

$ cd ~/src/openthread
$ sudo ./build/posix/src/posix/ot-daemon -v \
    'spinel+hdlc+forkpty://build/simulation/examples/apps/ncp/ot-rcp?forkpty-arg=2'

כשהפעולה מבוצעת בהצלחה, ot-daemon במצב 'מילולי' יוצר פלט דומה לזה:

ot-daemon[12463]: Running OPENTHREAD/thread-reference-20200818-1938-g0f10480ed; POSIX; Aug 30 2022 10:55:05
ot-daemon[12463]: Thread version: 4
ot-daemon[12463]: Thread interface: wpan0
ot-daemon[12463]: RCP version: OPENTHREAD/thread-reference-20200818-1938-g0f10480ed; SIMULATION; Aug 30 2022 10:54:10

צריך להשאיר את המסוף פתוח ולהפעיל אותו ברקע. לא מזינים בו פקודות נוספות.

3. שימוש ב-ot-ctl כדי להצטרף לרשת

עדיין לא הזמנו את צומת 2 (ה-RCP של ot-daemon) לאף רשת Thread. כאן נכנסת לתמונה ot-ctl. ot-ctl משתמש באותו CLI כמו אפליקציית OpenThread CLI, ולכן אפשר לשלוט בצמתים של ot-daemon באותו אופן שבו משתמשים בסימולציה אחרת של מכשירי Thread.

בחלון שלישי במסוף, מפעילים את ot-ctl:

$ sudo ./build/posix/src/posix/ot-ctl
>

הערה: אם ההודעה > לא מופיעה אחרי הרצת הפקודה הזו, מקישים על enter.

תשתמשו ב-ot-ctl בחלון הטרמינל השלישי כדי לנהל את צומת 2 (צומת ה-RCP) שהתחלת בחלון השני של המסוף עם ot-daemon. בדיקת state של צומת 2:

> state
disabled
Done

יש להוריד את eui64 של צומת 2 כדי להגביל את ההצטרפות ל-joiner הספציפי:

> eui64
18b4300000000001
Done

בצומת 1 (חלון הטרמינל הראשון), מפעילים את הנציב ומגבילים את ההצטרפות רק ל-eui64:

> commissioner start
Done
> commissioner joiner add 18b4300000000001 J01NME
Done

בצומת 2 (חלון שלישי במסוף), מעלים את ממשק הרשת ומצטרפים לרשת:

> ifconfig up
Done
> joiner start J01NME
Done

... ממתינים כמה שניות לאישור ...

Join success

כחברה בתוכנית RCP (צומת 2) אימתה בהצלחה את הנציב (צומת 1) וקיבלה את פרטי הכניסה של Thread Network.

מצטרפים עכשיו לצומת 2 לרשת ה-Thread:

> thread start
Done

4. אימות הרשת

בדוק את state בצומת 2 כדי לוודא שהוא הצטרף לרשת. תוך שתי דקות, צומת 2 עובר מ-child ל-router:

> state
child
Done
...
> state
router
Done

5. אימות הקישוריות

יש לצאת מ-ot-ctl באמצעות הפקודה Ctrl+D או exit, ובשורת הפקודה של המחשב המארח שלך, שמפינגת את צומת 1, באמצעות ה-EID עם הפקודה ping6. אם מופע RCP ot-daemon מחובר לרשת ה-Thread ומתקשר אליה, הפינג מצליח:

$ ping6 -c 4 fd55:cf34:dea5:7994:460:872c:e807:c4ab
PING fd55:cf34:dea5:7994:460:872c:e807:c4ab (fd55:cf34:dea5:7994:460:872c:e807:c4ab): 56 data bytes
64 bytes from fd55:cf34:dea5:7994:460:872c:e807:c4ab: icmp_seq=0 ttl=64 time=4.568 ms
64 bytes from fd55:cf34:dea5:7994:460:872c:e807:c4ab: icmp_seq=1 ttl=64 time=6.396 ms
64 bytes from fd55:cf34:dea5:7994:460:872c:e807:c4ab: icmp_seq=2 ttl=64 time=7.594 ms
64 bytes from fd55:cf34:dea5:7994:460:872c:e807:c4ab: icmp_seq=3 ttl=64 time=5.461 ms
--- fd55:cf34:dea5:7994:460:872c:e807:c4ab ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max/stddev = 4.568/6.005/7.594/1.122 ms

7. מזל טוב!

סימנתם בהצלחה את רשת השרשורים הראשונה שלכם באמצעות OpenThread. נפלא!

ב-Codelab הזה למדתם איך:

  • הגדרת ארגז הכלים לפיתוח של OpenThread
  • סימולציה של רשת שרשורים
  • אימות צמתים של שרשור
  • ניהול רשת של Thread עם OpenThread Daemon

מידע נוסף זמין במאמרים הבאים: