FILE
hclge_comm_rss.c
File preview with syntax highlighting.
linux-6.19.14/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_rss.c
1// SPDX-License-Identifier: GPL-2.0+ 2// Copyright (c) 2021-2021 Hisilicon Limited. 3#include <linux/skbuff.h> 4 5#include "hnae3.h" 6#include "hclge_comm_cmd.h" 7#include "hclge_comm_rss.h" 8 9static const u8 hclge_comm_hash_key[] = { 10 0x6D, 0x5A, 0x56, 0xDA, 0x25, 0x5B, 0x0E, 0xC2, 11 0x41, 0x67, 0x25, 0x3D, 0x43, 0xA3, 0x8F, 0xB0, 12 0xD0, 0xCA, 0x2B, 0xCB, 0xAE, 0x7B, 0x30, 0xB4, 13 0x77, 0xCB, 0x2D, 0xA3, 0x80, 0x30, 0xF2, 0x0C, 14 0x6A, 0x42, 0xB7, 0x3B, 0xBE, 0xAC, 0x01, 0xFA 15}; 16 17static void 18hclge_comm_init_rss_tuple(struct hnae3_ae_dev *ae_dev, 19 struct hclge_comm_rss_tuple_cfg *rss_tuple_cfg) 20{ 21 rss_tuple_cfg->ipv4_tcp_en = HCLGE_COMM_RSS_INPUT_TUPLE_OTHER; 22 rss_tuple_cfg->ipv4_udp_en = HCLGE_COMM_RSS_INPUT_TUPLE_OTHER; 23 rss_tuple_cfg->ipv4_sctp_en = HCLGE_COMM_RSS_INPUT_TUPLE_SCTP; 24 rss_tuple_cfg->ipv4_fragment_en = HCLGE_COMM_RSS_INPUT_TUPLE_OTHER; 25 rss_tuple_cfg->ipv6_tcp_en = HCLGE_COMM_RSS_INPUT_TUPLE_OTHER; 26 rss_tuple_cfg->ipv6_udp_en = HCLGE_COMM_RSS_INPUT_TUPLE_OTHER; 27 rss_tuple_cfg->ipv6_sctp_en = 28 ae_dev->dev_version <= HNAE3_DEVICE_VERSION_V2 ? 29 HCLGE_COMM_RSS_INPUT_TUPLE_SCTP_NO_PORT : 30 HCLGE_COMM_RSS_INPUT_TUPLE_SCTP; 31 rss_tuple_cfg->ipv6_fragment_en = HCLGE_COMM_RSS_INPUT_TUPLE_OTHER; 32} 33 34int hclge_comm_rss_init_cfg(struct hnae3_handle *nic, 35 struct hnae3_ae_dev *ae_dev, 36 struct hclge_comm_rss_cfg *rss_cfg) 37{ 38 u16 rss_ind_tbl_size = ae_dev->dev_specs.rss_ind_tbl_size; 39 int rss_algo = HCLGE_COMM_RSS_HASH_ALGO_TOEPLITZ; 40 u16 *rss_ind_tbl; 41 42 if (nic->flags & HNAE3_SUPPORT_VF) 43 rss_cfg->rss_size = nic->kinfo.rss_size; 44 45 if (ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V2) 46 rss_algo = HCLGE_COMM_RSS_HASH_ALGO_SIMPLE; 47 48 hclge_comm_init_rss_tuple(ae_dev, &rss_cfg->rss_tuple_sets); 49 50 rss_cfg->rss_algo = rss_algo; 51 52 rss_ind_tbl = devm_kcalloc(&ae_dev->pdev->dev, rss_ind_tbl_size, 53 sizeof(*rss_ind_tbl), GFP_KERNEL); 54 if (!rss_ind_tbl) 55 return -ENOMEM; 56 57 rss_cfg->rss_indirection_tbl = rss_ind_tbl; 58 memcpy(rss_cfg->rss_hash_key, hclge_comm_hash_key, 59 HCLGE_COMM_RSS_KEY_SIZE); 60 61 hclge_comm_rss_indir_init_cfg(ae_dev, rss_cfg); 62 63 return 0; 64} 65EXPORT_SYMBOL_GPL(hclge_comm_rss_init_cfg); 66 67void hclge_comm_get_rss_tc_info(u16 rss_size, u8 hw_tc_map, u16 *tc_offset, 68 u16 *tc_valid, u16 *tc_size) 69{ 70 u16 roundup_size; 71 u32 i; 72 73 roundup_size = roundup_pow_of_two(rss_size); 74 roundup_size = ilog2(roundup_size); 75 76 for (i = 0; i < HCLGE_COMM_MAX_TC_NUM; i++) { 77 tc_valid[i] = 1; 78 tc_size[i] = roundup_size; 79 tc_offset[i] = (hw_tc_map & BIT(i)) ? rss_size * i : 0; 80 } 81} 82EXPORT_SYMBOL_GPL(hclge_comm_get_rss_tc_info); 83 84int hclge_comm_set_rss_tc_mode(struct hclge_comm_hw *hw, u16 *tc_offset, 85 u16 *tc_valid, u16 *tc_size) 86{ 87 struct hclge_comm_rss_tc_mode_cmd *req; 88 struct hclge_desc desc; 89 unsigned int i; 90 int ret; 91 92 req = (struct hclge_comm_rss_tc_mode_cmd *)desc.data; 93 94 hclge_comm_cmd_setup_basic_desc(&desc, HCLGE_OPC_RSS_TC_MODE, false); 95 for (i = 0; i < HCLGE_COMM_MAX_TC_NUM; i++) { 96 u16 mode = 0; 97 98 hnae3_set_bit(mode, HCLGE_COMM_RSS_TC_VALID_B, 99 (tc_valid[i] & 0x1)); 100 hnae3_set_field(mode, HCLGE_COMM_RSS_TC_SIZE_M, 101 HCLGE_COMM_RSS_TC_SIZE_S, tc_size[i]); 102 hnae3_set_bit(mode, HCLGE_COMM_RSS_TC_SIZE_MSB_B, 103 tc_size[i] >> HCLGE_COMM_RSS_TC_SIZE_MSB_OFFSET & 104 0x1); 105 hnae3_set_field(mode, HCLGE_COMM_RSS_TC_OFFSET_M, 106 HCLGE_COMM_RSS_TC_OFFSET_S, tc_offset[i]); 107 108 req->rss_tc_mode[i] = cpu_to_le16(mode); 109 } 110 111 ret = hclge_comm_cmd_send(hw, &desc, 1); 112 if (ret) 113 dev_err(&hw->cmq.csq.pdev->dev, 114 "failed to set rss tc mode, ret = %d.\n", ret); 115 116 return ret; 117} 118EXPORT_SYMBOL_GPL(hclge_comm_set_rss_tc_mode); 119 120int hclge_comm_set_rss_hash_key(struct hclge_comm_rss_cfg *rss_cfg, 121 struct hclge_comm_hw *hw, const u8 *key, 122 const u8 hfunc) 123{ 124 u8 hash_algo; 125 int ret; 126 127 ret = hclge_comm_parse_rss_hfunc(rss_cfg, hfunc, &hash_algo); 128 if (ret) 129 return ret; 130 131 /* Set the RSS Hash Key if specififed by the user */ 132 if (key) { 133 ret = hclge_comm_set_rss_algo_key(hw, hash_algo, key); 134 if (ret) 135 return ret; 136 137 /* Update the shadow RSS key with user specified qids */ 138 memcpy(rss_cfg->rss_hash_key, key, HCLGE_COMM_RSS_KEY_SIZE); 139 } else { 140 ret = hclge_comm_set_rss_algo_key(hw, hash_algo, 141 rss_cfg->rss_hash_key); 142 if (ret) 143 return ret; 144 } 145 rss_cfg->rss_algo = hash_algo; 146 147 return 0; 148} 149EXPORT_SYMBOL_GPL(hclge_comm_set_rss_hash_key); 150 151int hclge_comm_set_rss_tuple(struct hnae3_ae_dev *ae_dev, 152 struct hclge_comm_hw *hw, 153 struct hclge_comm_rss_cfg *rss_cfg, 154 const struct ethtool_rxfh_fields *nfc) 155{ 156 struct hclge_comm_rss_input_tuple_cmd *req; 157 struct hclge_desc desc; 158 int ret; 159 160 if (nfc->data & 161 ~(RXH_IP_SRC | RXH_IP_DST | RXH_L4_B_0_1 | RXH_L4_B_2_3)) 162 return -EINVAL; 163 164 req = (struct hclge_comm_rss_input_tuple_cmd *)desc.data; 165 hclge_comm_cmd_setup_basic_desc(&desc, HCLGE_OPC_RSS_INPUT_TUPLE, 166 false); 167 168 ret = hclge_comm_init_rss_tuple_cmd(rss_cfg, nfc, ae_dev, req); 169 if (ret) { 170 dev_err(&hw->cmq.csq.pdev->dev, 171 "failed to init rss tuple cmd, ret = %d.\n", ret); 172 return ret; 173 } 174 175 ret = hclge_comm_cmd_send(hw, &desc, 1); 176 if (ret) { 177 dev_err(&hw->cmq.csq.pdev->dev, 178 "failed to set rss tuple, ret = %d.\n", ret); 179 return ret; 180 } 181 182 rss_cfg->rss_tuple_sets.ipv4_tcp_en = req->ipv4_tcp_en; 183 rss_cfg->rss_tuple_sets.ipv4_udp_en = req->ipv4_udp_en; 184 rss_cfg->rss_tuple_sets.ipv4_sctp_en = req->ipv4_sctp_en; 185 rss_cfg->rss_tuple_sets.ipv4_fragment_en = req->ipv4_fragment_en; 186 rss_cfg->rss_tuple_sets.ipv6_tcp_en = req->ipv6_tcp_en; 187 rss_cfg->rss_tuple_sets.ipv6_udp_en = req->ipv6_udp_en; 188 rss_cfg->rss_tuple_sets.ipv6_sctp_en = req->ipv6_sctp_en; 189 rss_cfg->rss_tuple_sets.ipv6_fragment_en = req->ipv6_fragment_en; 190 return 0; 191} 192EXPORT_SYMBOL_GPL(hclge_comm_set_rss_tuple); 193 194u32 hclge_comm_get_rss_key_size(struct hnae3_handle *handle) 195{ 196 return HCLGE_COMM_RSS_KEY_SIZE; 197} 198EXPORT_SYMBOL_GPL(hclge_comm_get_rss_key_size); 199 200int hclge_comm_parse_rss_hfunc(struct hclge_comm_rss_cfg *rss_cfg, 201 const u8 hfunc, u8 *hash_algo) 202{ 203 switch (hfunc) { 204 case ETH_RSS_HASH_TOP: 205 *hash_algo = HCLGE_COMM_RSS_HASH_ALGO_TOEPLITZ; 206 return 0; 207 case ETH_RSS_HASH_XOR: 208 *hash_algo = HCLGE_COMM_RSS_HASH_ALGO_SIMPLE; 209 return 0; 210 case ETH_RSS_HASH_NO_CHANGE: 211 *hash_algo = rss_cfg->rss_algo; 212 return 0; 213 default: 214 return -EINVAL; 215 } 216} 217 218void hclge_comm_rss_indir_init_cfg(struct hnae3_ae_dev *ae_dev, 219 struct hclge_comm_rss_cfg *rss_cfg) 220{ 221 u16 i; 222 /* Initialize RSS indirect table */ 223 for (i = 0; i < ae_dev->dev_specs.rss_ind_tbl_size; i++) 224 rss_cfg->rss_indirection_tbl[i] = i % rss_cfg->rss_size; 225} 226EXPORT_SYMBOL_GPL(hclge_comm_rss_indir_init_cfg); 227 228int hclge_comm_get_rss_tuple(struct hclge_comm_rss_cfg *rss_cfg, int flow_type, 229 u8 *tuple_sets) 230{ 231 switch (flow_type) { 232 case TCP_V4_FLOW: 233 *tuple_sets = rss_cfg->rss_tuple_sets.ipv4_tcp_en; 234 break; 235 case UDP_V4_FLOW: 236 *tuple_sets = rss_cfg->rss_tuple_sets.ipv4_udp_en; 237 break; 238 case TCP_V6_FLOW: 239 *tuple_sets = rss_cfg->rss_tuple_sets.ipv6_tcp_en; 240 break; 241 case UDP_V6_FLOW: 242 *tuple_sets = rss_cfg->rss_tuple_sets.ipv6_udp_en; 243 break; 244 case SCTP_V4_FLOW: 245 *tuple_sets = rss_cfg->rss_tuple_sets.ipv4_sctp_en; 246 break; 247 case SCTP_V6_FLOW: 248 *tuple_sets = rss_cfg->rss_tuple_sets.ipv6_sctp_en; 249 break; 250 case IPV4_FLOW: 251 case IPV6_FLOW: 252 *tuple_sets = HCLGE_COMM_S_IP_BIT | HCLGE_COMM_D_IP_BIT; 253 break; 254 default: 255 return -EINVAL; 256 } 257 258 return 0; 259} 260EXPORT_SYMBOL_GPL(hclge_comm_get_rss_tuple); 261 262static void 263hclge_comm_append_rss_msb_info(struct hclge_comm_rss_ind_tbl_cmd *req, 264 u16 qid, u32 j) 265{ 266 u8 rss_msb_oft; 267 u8 rss_msb_val; 268 269 rss_msb_oft = 270 j * HCLGE_COMM_RSS_CFG_TBL_BW_H / BITS_PER_BYTE; 271 rss_msb_val = (qid >> HCLGE_COMM_RSS_CFG_TBL_BW_L & 0x1) << 272 (j * HCLGE_COMM_RSS_CFG_TBL_BW_H % BITS_PER_BYTE); 273 req->rss_qid_h[rss_msb_oft] |= rss_msb_val; 274} 275 276int hclge_comm_set_rss_indir_table(struct hnae3_ae_dev *ae_dev, 277 struct hclge_comm_hw *hw, const u16 *indir) 278{ 279 struct hclge_comm_rss_ind_tbl_cmd *req; 280 struct hclge_desc desc; 281 u16 rss_cfg_tbl_num; 282 int ret; 283 u16 qid; 284 u16 i; 285 u32 j; 286 287 req = (struct hclge_comm_rss_ind_tbl_cmd *)desc.data; 288 rss_cfg_tbl_num = ae_dev->dev_specs.rss_ind_tbl_size / 289 HCLGE_COMM_RSS_CFG_TBL_SIZE; 290 291 for (i = 0; i < rss_cfg_tbl_num; i++) { 292 hclge_comm_cmd_setup_basic_desc(&desc, 293 HCLGE_OPC_RSS_INDIR_TABLE, 294 false); 295 296 req->start_table_index = 297 cpu_to_le16(i * HCLGE_COMM_RSS_CFG_TBL_SIZE); 298 req->rss_set_bitmap = 299 cpu_to_le16(HCLGE_COMM_RSS_SET_BITMAP_MSK); 300 for (j = 0; j < HCLGE_COMM_RSS_CFG_TBL_SIZE; j++) { 301 qid = indir[i * HCLGE_COMM_RSS_CFG_TBL_SIZE + j]; 302 req->rss_qid_l[j] = qid & 0xff; 303 hclge_comm_append_rss_msb_info(req, qid, j); 304 } 305 ret = hclge_comm_cmd_send(hw, &desc, 1); 306 if (ret) { 307 dev_err(&hw->cmq.csq.pdev->dev, 308 "failed to configure rss table, ret = %d.\n", 309 ret); 310 return ret; 311 } 312 } 313 return 0; 314} 315EXPORT_SYMBOL_GPL(hclge_comm_set_rss_indir_table); 316 317int hclge_comm_set_rss_input_tuple(struct hclge_comm_hw *hw, 318 struct hclge_comm_rss_cfg *rss_cfg) 319{ 320 struct hclge_comm_rss_input_tuple_cmd *req; 321 struct hclge_desc desc; 322 int ret; 323 324 hclge_comm_cmd_setup_basic_desc(&desc, HCLGE_OPC_RSS_INPUT_TUPLE, 325 false); 326 327 req = (struct hclge_comm_rss_input_tuple_cmd *)desc.data; 328 329 req->ipv4_tcp_en = rss_cfg->rss_tuple_sets.ipv4_tcp_en; 330 req->ipv4_udp_en = rss_cfg->rss_tuple_sets.ipv4_udp_en; 331 req->ipv4_sctp_en = rss_cfg->rss_tuple_sets.ipv4_sctp_en; 332 req->ipv4_fragment_en = rss_cfg->rss_tuple_sets.ipv4_fragment_en; 333 req->ipv6_tcp_en = rss_cfg->rss_tuple_sets.ipv6_tcp_en; 334 req->ipv6_udp_en = rss_cfg->rss_tuple_sets.ipv6_udp_en; 335 req->ipv6_sctp_en = rss_cfg->rss_tuple_sets.ipv6_sctp_en; 336 req->ipv6_fragment_en = rss_cfg->rss_tuple_sets.ipv6_fragment_en; 337 338 ret = hclge_comm_cmd_send(hw, &desc, 1); 339 if (ret) 340 dev_err(&hw->cmq.csq.pdev->dev, 341 "failed to configure rss input, ret = %d.\n", ret); 342 return ret; 343} 344EXPORT_SYMBOL_GPL(hclge_comm_set_rss_input_tuple); 345 346void hclge_comm_get_rss_hash_info(struct hclge_comm_rss_cfg *rss_cfg, u8 *key, 347 u8 *hfunc) 348{ 349 /* Get hash algorithm */ 350 if (hfunc) { 351 switch (rss_cfg->rss_algo) { 352 case HCLGE_COMM_RSS_HASH_ALGO_TOEPLITZ: 353 *hfunc = ETH_RSS_HASH_TOP; 354 break; 355 case HCLGE_COMM_RSS_HASH_ALGO_SIMPLE: 356 *hfunc = ETH_RSS_HASH_XOR; 357 break; 358 default: 359 *hfunc = ETH_RSS_HASH_UNKNOWN; 360 break; 361 } 362 } 363 364 /* Get the RSS Key required by the user */ 365 if (key) 366 memcpy(key, rss_cfg->rss_hash_key, HCLGE_COMM_RSS_KEY_SIZE); 367} 368EXPORT_SYMBOL_GPL(hclge_comm_get_rss_hash_info); 369 370void hclge_comm_get_rss_indir_tbl(struct hclge_comm_rss_cfg *rss_cfg, 371 u32 *indir, u16 rss_ind_tbl_size) 372{ 373 u16 i; 374 375 if (!indir) 376 return; 377 378 for (i = 0; i < rss_ind_tbl_size; i++) 379 indir[i] = rss_cfg->rss_indirection_tbl[i]; 380} 381EXPORT_SYMBOL_GPL(hclge_comm_get_rss_indir_tbl); 382 383int hclge_comm_set_rss_algo_key(struct hclge_comm_hw *hw, const u8 hfunc, 384 const u8 *key) 385{ 386 struct hclge_comm_rss_config_cmd *req; 387 unsigned int key_offset = 0; 388 struct hclge_desc desc; 389 int key_counts; 390 int key_size; 391 int ret; 392 393 key_counts = HCLGE_COMM_RSS_KEY_SIZE; 394 req = (struct hclge_comm_rss_config_cmd *)desc.data; 395 396 while (key_counts) { 397 hclge_comm_cmd_setup_basic_desc(&desc, 398 HCLGE_OPC_RSS_GENERIC_CONFIG, 399 false); 400 401 req->hash_config |= (hfunc & HCLGE_COMM_RSS_HASH_ALGO_MASK); 402 req->hash_config |= 403 (key_offset << HCLGE_COMM_RSS_HASH_KEY_OFFSET_B); 404 405 key_size = min(HCLGE_COMM_RSS_HASH_KEY_NUM, key_counts); 406 memcpy(req->hash_key, 407 key + key_offset * HCLGE_COMM_RSS_HASH_KEY_NUM, 408 key_size); 409 410 key_counts -= key_size; 411 key_offset++; 412 ret = hclge_comm_cmd_send(hw, &desc, 1); 413 if (ret) { 414 dev_err(&hw->cmq.csq.pdev->dev, 415 "failed to configure RSS key, ret = %d.\n", 416 ret); 417 return ret; 418 } 419 } 420 421 return 0; 422} 423EXPORT_SYMBOL_GPL(hclge_comm_set_rss_algo_key); 424 425static u8 hclge_comm_get_rss_hash_bits(const struct ethtool_rxfh_fields *nfc) 426{ 427 u8 hash_sets = nfc->data & RXH_L4_B_0_1 ? HCLGE_COMM_S_PORT_BIT : 0; 428 429 if (nfc->data & RXH_L4_B_2_3) 430 hash_sets |= HCLGE_COMM_D_PORT_BIT; 431 else 432 hash_sets &= ~HCLGE_COMM_D_PORT_BIT; 433 434 if (nfc->data & RXH_IP_SRC) 435 hash_sets |= HCLGE_COMM_S_IP_BIT; 436 else 437 hash_sets &= ~HCLGE_COMM_S_IP_BIT; 438 439 if (nfc->data & RXH_IP_DST) 440 hash_sets |= HCLGE_COMM_D_IP_BIT; 441 else 442 hash_sets &= ~HCLGE_COMM_D_IP_BIT; 443 444 if (nfc->flow_type == SCTP_V4_FLOW || nfc->flow_type == SCTP_V6_FLOW) 445 hash_sets |= HCLGE_COMM_V_TAG_BIT; 446 447 return hash_sets; 448} 449 450int hclge_comm_init_rss_tuple_cmd(struct hclge_comm_rss_cfg *rss_cfg, 451 const struct ethtool_rxfh_fields *nfc, 452 struct hnae3_ae_dev *ae_dev, 453 struct hclge_comm_rss_input_tuple_cmd *req) 454{ 455 u8 tuple_sets; 456 457 req->ipv4_tcp_en = rss_cfg->rss_tuple_sets.ipv4_tcp_en; 458 req->ipv4_udp_en = rss_cfg->rss_tuple_sets.ipv4_udp_en; 459 req->ipv4_sctp_en = rss_cfg->rss_tuple_sets.ipv4_sctp_en; 460 req->ipv4_fragment_en = rss_cfg->rss_tuple_sets.ipv4_fragment_en; 461 req->ipv6_tcp_en = rss_cfg->rss_tuple_sets.ipv6_tcp_en; 462 req->ipv6_udp_en = rss_cfg->rss_tuple_sets.ipv6_udp_en; 463 req->ipv6_sctp_en = rss_cfg->rss_tuple_sets.ipv6_sctp_en; 464 req->ipv6_fragment_en = rss_cfg->rss_tuple_sets.ipv6_fragment_en; 465 466 tuple_sets = hclge_comm_get_rss_hash_bits(nfc); 467 switch (nfc->flow_type) { 468 case TCP_V4_FLOW: 469 req->ipv4_tcp_en = tuple_sets; 470 break; 471 case TCP_V6_FLOW: 472 req->ipv6_tcp_en = tuple_sets; 473 break; 474 case UDP_V4_FLOW: 475 req->ipv4_udp_en = tuple_sets; 476 break; 477 case UDP_V6_FLOW: 478 req->ipv6_udp_en = tuple_sets; 479 break; 480 case SCTP_V4_FLOW: 481 req->ipv4_sctp_en = tuple_sets; 482 break; 483 case SCTP_V6_FLOW: 484 if (ae_dev->dev_version <= HNAE3_DEVICE_VERSION_V2 && 485 (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3))) 486 return -EINVAL; 487 488 req->ipv6_sctp_en = tuple_sets; 489 break; 490 case IPV4_FLOW: 491 req->ipv4_fragment_en = HCLGE_COMM_RSS_INPUT_TUPLE_OTHER; 492 break; 493 case IPV6_FLOW: 494 req->ipv6_fragment_en = HCLGE_COMM_RSS_INPUT_TUPLE_OTHER; 495 break; 496 default: 497 return -EINVAL; 498 } 499 500 return 0; 501} 502 503u64 hclge_comm_convert_rss_tuple(u8 tuple_sets) 504{ 505 u64 tuple_data = 0; 506 507 if (tuple_sets & HCLGE_COMM_D_PORT_BIT) 508 tuple_data |= RXH_L4_B_2_3; 509 if (tuple_sets & HCLGE_COMM_S_PORT_BIT) 510 tuple_data |= RXH_L4_B_0_1; 511 if (tuple_sets & HCLGE_COMM_D_IP_BIT) 512 tuple_data |= RXH_IP_DST; 513 if (tuple_sets & HCLGE_COMM_S_IP_BIT) 514 tuple_data |= RXH_IP_SRC; 515 516 return tuple_data; 517} 518EXPORT_SYMBOL_GPL(hclge_comm_convert_rss_tuple);
~/
Read-only file preview.