Skip to content

Commit

Permalink
update site
Browse files Browse the repository at this point in the history
  • Loading branch information
suoyuan666 committed Jul 25, 2024
1 parent 238b72f commit b7fea7f
Show file tree
Hide file tree
Showing 8 changed files with 172 additions and 2 deletions.
131 changes: 131 additions & 0 deletions src/content/blog/CS144_notes_002.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
---
title: "字节序 & IPV4 地址 & ARP 协议"
author: suo yuan
pubDatetime: 2024-07-25T06:28:24Z
featured: false
draft: false
tags:
- CS144_notes
description: "CS114 课程的课程笔记"
---

# 字节序 & IPV4 地址 & ARP 协议

## 字节排版和格式

假设要发送 1024 ,十六进制是 0x0400 来表示。

在小端法表示中,最低有效字节位于最低地址,也就是 0x00, 0x04 这么存储。

在大端法表示中,最高有效字节位于最低地址,也就是 0x04, 0x00 这么存储。

但通信双方处理器使用的的字节序未必一致。例如 Intel 和 AMD x86 处理器使用小端法,不过一些处理器支持双端法,然后由操作系统决定到底用小端还是大端。

协议规范规定了使用大端,互联网所有协议都使用大端字节序。

如果自身机器是小端字节序的话,可以写个测试:

假设 TCP 端口为 80,存一个变量 `http_port = 80`

```c
uint16_t http_port = 80;
if (packet->port == http_port) { ... } // ERROR
```
此时就可以比对,`http_port` 是小端存储,但 `packet->port` 则是大端,虽然实际上要存储的值都是 80,但测试失败。
为了简化这个过程,C 提供了一些库函数: `htons()`, `ntohs()`, `htonl()`, `ntohl()`
- htons: host to network short
- ntohl: network to host long
```c
#include <arpa/inet.h>
uint http_port = 80;
uint16_t packet_port = ntohs(packet->port)
if (packet_port == http_port) { ... } // OK
```

对于小端字节序表示来说,`ntohs()``htons()` 会调换字节的顺序,对于大端字节序来说,二者什么也不做,只是将参数返回。

## IPV4 地址

IPV4 地址长度为 32 位。通常分成4组写,例如: 192.168.1.1

除了 IP 地址的标示,还有网络掩码 (netmask)。例如网络掩码 255.255.255.0,表示 IP 地址 和自己的前三个八位字节匹配的在同一网络中。而 255.255.252.0 则表示前 22 位相同的和自己在同一网络中。

这就可以对两个 IP 地址和它们自己的掩码按位与来判断是否在同一网络中

```c
if ((A & netmask) == (B & netmask)) { ... }
```
可以使用 `ip addr` 查看自己的 IP 地址,有些发行版默认不装 [net-tools](https://net-tools.sourceforge.io/) 也就无法使用 `ipconfig`,但应该会带 [iproute2](https://git.kernel.org/pub/scm/network/iproute2/iproute2.git)。
### 地址结构
传统分为三种
- 0 network(1 -> 7) host(8 -> 31)
- 1 0 network(2 -> 15) host(16 -> 31)
- 1 1 0 network(3 -> 23) host(24 -> 31)
其中,network 部分表示为 administrative domain,比如 MIT,Stanford,host 部分具体指是该网络的哪个设备。
但这种方式无法应对早就膨胀的互联网主机数量。
现在 IPV4 已经结构化,称为 CIDR (Classless Inter-Domain Routing)。CIDR 可以自定义前缀长度,其大小为 2 的幂次。当说到 CIDR 地址时,也就是在说就是网络掩码的长度,例如 `192.168.1.0/24`,表示长度为 24 的网络掩码,表示其容纳了 256 个地址,`/16` 是长度为16的网络掩码,描述了 65536 个地址。
[IANA](https://en.wikipedia.org/wiki/Internet_Assigned_Numbers_Authority) (Internet Assigned Numbers Authority)组织负责分配 IP 地址,其背后是 [ICANN](https://en.wikipedia.org/wiki/ICANN) (Internet Corporation for Assigned Names and Numbers),ICANN 将工作委托给了 IANA。IANA 向区域互联网注册机构 (Regional Internet Registries, RIRs)分发了 `/8` (1600 万个地址),每个州有自己的 RIR,目前总共有五个 RIR。
> - 美洲互联网号码注册管理机构(American Registry for Internet Numbers,ARIN)管理北美、南极洲和部分加勒比地区事务
> - 欧洲IP网络资源协调中心(RIPE Network Coordination Centre,RIPE NCC)管理欧洲、中东和中亚地区事务
> - 亚太网络信息中心(Asia-Pacific Network Information Centre,APNIC)管理亚洲和太平洋地区事务
> - 拉丁美洲及加勒比地区互联网地址注册管理机构(Latin American and Caribbean Internet Address Registry,LACNIC)管理拉丁美洲和部分加勒比地区事务
> - 非洲网络信息中心(African Network Information Centre,AfriNIC)管理非洲事务
## Longest Prefix Match
路由器通过转发表决定转发数据包的链路,当数据包到达时,路由器会在转发表找到和该地址最匹配的条目,并以此决定转发链路。
最长前缀匹配 (Longest Prefix Match, LPM)是 IP 路由用来决定转发地址的算法。
## ARP, Address Resolution Protocol
ARP 协议是网络层使用,用于发现与其直连的网络地址的 link 地址。设备自己有 IP 地址,但是它需要将数据报发送到哪个 link 上,ARP 协议解决了这个问题。每一层服务都有每一层用于标识的地址,IP 是网络层的地址,而 link 地址标示了特定的网卡,例如,Ethernet 地址是 48 bit。
48 bit 的 Ethernet 地址以冒号分隔的 6 个组形式写入,例如: `0:18:e7:f3:ce:1a`。
假设下面这个场景:
![ARP协议图一](../img/CS144/gateway.png)
中间的网关有两个网卡,分别连 A 和 B 两个主机。网关本身就是位于 A 所属的这部分网络中,但网关在只有一个 IP 地址的情况下无法正常工作。所以网卡或路由器具有多个接口,也就具有多个 IP 地址。
![ARP协议图二](../img/CS144/new_gateway.png)
假设 A 要向 B 发送数据包。首先判断目的地是否和自己处于同一网络内,网络掩码会表明这一点。
所以 A 需要通过网关来发包,该数据报网络层目标是 `171.43.22.5`,但链路层的目标为网关的地址 `0:18:e7:f3:ce:1a`。当网关收到数据报后,网关会为它的下一跳确定为节点 B,然后将其放到 B 的链路层帧中。
这里存在一个问题,A 知道需要通过 `192.168.0.1` 的网关发送数据包,所以它需要有和 `192.168.0.1` 关联的 link 地址,但如何获取这个地址。
这里通过一种方式将网络层地址映射到其对应的链路层地址。这里使用的就是 ARP 协议执行此操作。
ARP 是一种简单的 "request-reply" 的协议。
每个节点都保留在网络中 IP 地址到链路层地址映射的缓存,如果节点需要将数据报发送到它没有映射的 IP 地址,就需要发送一个请求,内容类似 “谁的 IP 地址是 XXX”,对应 IP 地址的节点再给出回应“我是这个地址”,这个回应就带着链路层地址。收到这个回复后,节点就可以建立映射缓存并发包。一个节点发出请求,网络中的每个节点都会收到该数据包。
ARP 请求时包含请求者的 IP 地址和链路层地址,以便于收到的一方可以插入或更新自己的映射缓存。这种映射缓存保存的时间取决于其操作系统。
![ARP协议图](../img/CS144/arp_protocal.png)
- Hardware: 此请求或响应应用于哪个链路层
- Protocol: 此请求或响应针对的网络协议
- opcode: 该数据报是请求还是响应
- length 指长度,比如 Ethernet 48 bit 长度就是 6,而 IPV4 地址长度则是 4。
这些字段都会以大端字节序来存储。
最开始 ARP 规范认为回应者应该单播发给请求者,但现在广播更加普遍。
29 changes: 29 additions & 0 deletions src/content/blog/notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,32 @@ NVIDIA + XWayland 还是很难绷,还是等到 nvidia-driver stable 更新到
zed stable for linux 已经发布,可以根据 [zed docs 上提供的办法](https://zed.dev/docs/linux)下载安装。

我本身不是 Rust 开发者,所以就试着打开了我 C++ 的小项目,总体来说还是不错的,有我看得下去的主题,内置 `clangd` 的支持,不过貌似没有对 `clang-tidy``clang-format` 的支持,如果还能有对 CMake 的支持就更好了。

## 菜狗对 glibc 的感慨

我一开始想写吐槽,后来感觉吐槽不太好。

起因是我出于某个原因,想去看一下 glibc 对 `fputc()` 的实现,`fputc` 函数本身写的不长,毕竟光调用别的宏了,我就不断的跳,直到跳到了这里:

```c
int
__overflow (FILE *f, int ch)
{
/* This is a single-byte stream. */
if (f->_mode == 0)
_IO_fwide (f, -1);
return _IO_OVERFLOW (f, ch);
}
```
`_IO_OVERFLOW` 也是一个宏函数,它完全展开长这个样子:
```c
((IO_validate_vtable ((*(__typeof__ (((struct _IO_FILE_plus){}).vtable)
*) (((char *) ((f)))
+ __builtin_offsetof (struct _IO_FILE_plus,
vtable)))))
->__overflow) (f, ch)
```

虽然最后了解了一下貌似是为了检查这个 vtable 合不合理用的,但还是感慨,第一次看到这样的宏展开。
8 changes: 6 additions & 2 deletions src/content/blog/nvidia_with_linux.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
---
title: NVIDIA 在 GNU/Linux 发行版上工作的技巧
title: NVIDIA 在 GNU/Linux 发行版上和 Wayland 一起工作的技巧
author: suo yuan
pubDatetime: 2024-07-19T01:21:25
featured: false
draft: false
tags:
- linux
- intro
description: "就是如何在 GNU/Linux 发行版中舒服的使用 NVIDIA 驱动"
description: "就是如何在 GNU/Linux 发行版使用 Wayland 的情况下中舒服的使用 NVIDIA 驱动"
---

# NVIDIA 在 GNU/Linux 发行版上工作的技巧
Expand Down Expand Up @@ -72,3 +72,7 @@ options nvidia NVreg_PreserveVideoMemoryAllocations=1
之后执行 `systemctl enable nvidia-resume.service` 并重启即可。

根据 Arch wiki 所述,这个不能和 NVIDIA 早启动一起使用,但实际上我一起用了,感觉没什么问题。

## 总结

用 Xorg 保心安,我当初用 Xorg 的时候还没这么些事。
Binary file added src/content/img/CS144/arp_protocal.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/content/img/CS144/gateway.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit b7fea7f

Please sign in to comment.